buildr4osgi 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/LICENSE +176 -0
  2. data/NOTICE +6 -0
  3. data/README.rdoc +50 -0
  4. data/Rakefile +45 -0
  5. data/buildr4osgi.gemspec +40 -0
  6. data/lib/buildr4osgi/compile/compiler.rb +54 -0
  7. data/lib/buildr4osgi/compile/ecj-3.4.1.jar +0 -0
  8. data/lib/buildr4osgi/compile.rb +16 -0
  9. data/lib/buildr4osgi/eclipse/feature.rb +271 -0
  10. data/lib/buildr4osgi/eclipse/plugin.rb +22 -0
  11. data/lib/buildr4osgi/eclipse.rb +17 -0
  12. data/lib/buildr4osgi/nature/eclipse.rb +80 -0
  13. data/lib/buildr4osgi/nature/java.rb +32 -0
  14. data/lib/buildr4osgi/nature/nature.rb +156 -0
  15. data/lib/buildr4osgi/nature/osgi.rb +32 -0
  16. data/lib/buildr4osgi/nature/scala.rb +32 -0
  17. data/lib/buildr4osgi/nature.rb +23 -0
  18. data/lib/buildr4osgi/osgi/bundle.rb +275 -0
  19. data/lib/buildr4osgi/osgi/bundle_package.rb +80 -0
  20. data/lib/buildr4osgi/osgi/container.rb +140 -0
  21. data/lib/buildr4osgi/osgi/library_extension.rb +174 -0
  22. data/lib/buildr4osgi/osgi/packaging.rb +129 -0
  23. data/lib/buildr4osgi/osgi/project_extension.rb +324 -0
  24. data/lib/buildr4osgi/osgi/registry.rb +61 -0
  25. data/lib/buildr4osgi/osgi/resolving_strategies.rb +104 -0
  26. data/lib/buildr4osgi/osgi/version.rb +131 -0
  27. data/lib/buildr4osgi/osgi.rb +24 -0
  28. data/lib/buildr4osgi.rb +37 -0
  29. data/rakelib/checks.rake +57 -0
  30. data/rakelib/doc.rake +92 -0
  31. data/rakelib/jekylltask.rb +120 -0
  32. data/rakelib/package.rake +73 -0
  33. data/rakelib/release.rake +149 -0
  34. data/rakelib/rspec.rake +73 -0
  35. data/rakelib/setup.rake +54 -0
  36. data/rakelib/stage.rake +206 -0
  37. data/spec/compile/compiler_spec.rb +30 -0
  38. data/spec/eclipse/feature_spec.rb +295 -0
  39. data/spec/nature/eclipse_spec.rb +46 -0
  40. data/spec/nature/java_spec.rb +45 -0
  41. data/spec/nature/osgi_spec.rb +63 -0
  42. data/spec/nature/scala_spec.rb +45 -0
  43. data/spec/nature_spec.rb +144 -0
  44. data/spec/osgi/bundle_package_spec.rb +32 -0
  45. data/spec/osgi/bundle_spec.rb +202 -0
  46. data/spec/osgi/container_spec.rb +93 -0
  47. data/spec/osgi/library_extension_spec.rb +142 -0
  48. data/spec/osgi/packaging_spec.rb +340 -0
  49. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/META-INF/ECLIPSEF.RSA +0 -0
  50. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/META-INF/ECLIPSEF.SF +20 -0
  51. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/META-INF/MANIFEST.MF +28 -0
  52. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/META-INF/eclipse.inf +3 -0
  53. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/about.html +28 -0
  54. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/fragment.properties +12 -0
  55. data/spec/osgi/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20090429-1800/runtime_registry_compatibility.jar +0 -0
  56. data/spec/osgi/project_extension_spec.rb +662 -0
  57. data/spec/osgi/registry_spec.rb +50 -0
  58. data/spec/osgi/version_spec.rb +127 -0
  59. data/spec/spec_helpers.rb +85 -0
  60. data/spec/tmp/remote/eclipse/org.eclipse.debug.ui/3.4.1.v20080811_r341/org.eclipse.debug.ui-3.4.1.v20080811_r341.jar +0 -0
  61. data/spec/tmp/remote/eclipse/org.eclipse.debug.ui/3.4.1.v20080811_r341/org.eclipse.debug.ui-3.4.1.v20080811_r341.pom +82 -0
  62. data/spec/tmp/remote/org/slf4j/jcl104-over-slf4j/1.5.8/jcl104-over-slf4j-1.5.8-sources.jar +0 -0
  63. data/spec/tmp/remote/org/slf4j/jcl104-over-slf4j/1.5.8/jcl104-over-slf4j-1.5.8.jar +0 -0
  64. data/spec/tmp/remote/org/slf4j/jcl104-over-slf4j/1.5.8/jcl104-over-slf4j-1.5.8.pom +30 -0
  65. data/spec/tmp/remote/org/slf4j/slf4j-api/1.5.8/slf4j-api-1.5.8-sources.jar +0 -0
  66. data/spec/tmp/remote/org/slf4j/slf4j-api/1.5.8/slf4j-api-1.5.8.jar +0 -0
  67. data/spec/tmp/remote/org/slf4j/slf4j-api/1.5.8/slf4j-api-1.5.8.pom +101 -0
  68. data/spec/tmp/remote/org/slf4j/slf4j-log4j12/1.5.8/slf4j-log4j12-1.5.8-sources.jar +0 -0
  69. data/spec/tmp/remote/org/slf4j/slf4j-log4j12/1.5.8/slf4j-log4j12-1.5.8.jar +0 -0
  70. data/spec/tmp/remote/org/slf4j/slf4j-log4j12/1.5.8/slf4j-log4j12-1.5.8.pom +56 -0
  71. metadata +142 -0
@@ -0,0 +1,22 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ class ::Buildr::Project
17
+ protected
18
+
19
+ # For now packaging as an OSGi Bundle is equivalent to packaging as an Eclipse plugin.
20
+ alias :package_as_plugin :package_as_bundle
21
+ alias :package_as_plugin_spec :package_as_bundle_spec
22
+ end
@@ -0,0 +1,17 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'buildr4osgi/eclipse/plugin'
17
+ require 'buildr4osgi/eclipse/feature'
@@ -0,0 +1,80 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module Buildr
17
+ module Nature
18
+ module Eclipse
19
+ include Extension
20
+
21
+ def eclipse
22
+ @eclipse ||= Buildr::Nature::Eclipse::Eclipse.new(self)
23
+ @eclipse
24
+ end
25
+
26
+ class Eclipse
27
+
28
+ attr_reader :options
29
+ def initialize(project)
30
+ @options = OptionsFromNatures.new(project)
31
+ end
32
+ end
33
+
34
+ class OptionsFromNatures
35
+ attr_accessor :m2_repo_var, :project #Remove when Eclipse patch in.
36
+
37
+ def initialize(project)
38
+ #super(project) uncomment when the patch for better Eclipse task is in.
39
+ @m2_repo_var = 'M2_REPO'
40
+ @project = project
41
+ end
42
+
43
+ def self.special_attr_accessor(*names)
44
+ names.each { |name|
45
+ module_eval %{
46
+
47
+ def #{name}= (value)
48
+ @#{name} = value.is_a?(Array) ? value : [value]
49
+ end
50
+
51
+ def #{name}
52
+ if @#{name}.nil?
53
+ if (project.parent && !project.parent.eclipse.options._#{name}.nil?)
54
+ @#{name} = project.parent.eclipse.options._#{name}
55
+ else
56
+ @#{name} = project.applicable_natures.collect{|n| n.eclipse.#{name}}.flatten.uniq
57
+ end
58
+ end
59
+ @#{name}
60
+ end
61
+
62
+ protected
63
+
64
+ def _#{name}
65
+ @#{name}
66
+ end
67
+ }
68
+ }
69
+ end
70
+
71
+ special_attr_accessor :natures, :builders, :classpath_containers
72
+
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ class Buildr::Project
79
+ include Buildr::Nature::Eclipse
80
+ end
@@ -0,0 +1,32 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module Buildr
17
+ class JavaNature < DefaultNature
18
+
19
+ def initialize()
20
+ super(:java)
21
+ eclipse.natures = "org.eclipse.jdt.core.javanature"
22
+ eclipse.builders = "org.eclipse.jdt.core.javabuilder"
23
+ eclipse.classpath_containers = "org.eclipse.jdt.launching.JRE_CONTAINER"
24
+ end
25
+
26
+ def applies(project)
27
+ File.exists? project.path_to(:src, :main, :java)
28
+ end
29
+ end
30
+
31
+ Nature::Registry.add_nature(JavaNature.new)
32
+ end
@@ -0,0 +1,156 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module Buildr
17
+
18
+ # The nature class is extended into project natures.
19
+ # See for example the JavaNature of the ScalaNature.
20
+ # A nature defines an unique id amonsgt all natures.
21
+ #
22
+ # These fields may be set when initializing an instance:
23
+ # eclipse_builders
24
+ # Used by the Eclipse task to output in .project, a builder being an Eclipse-specific background job to build a project.
25
+ # eclipse_natures
26
+ # Used by the Eclipse task to output in .classpath,
27
+ # an Eclipse nature is an Eclipse-specific concept used by the framework to determine the projects features.
28
+ # classpath_containers
29
+ # Used by the Eclipse task to output in .classpath,
30
+ # it is a special container identified by Eclipse for compilation.
31
+ #
32
+ class DefaultNature
33
+
34
+ class EclipseOptions
35
+
36
+ def self.attr_accessor(*names)
37
+ names.each { |name|
38
+ module_eval %{
39
+ attr_reader :#{name}
40
+
41
+ def #{name}= (value)
42
+ @#{name} = value.is_a?(Array) ? value : [value]
43
+
44
+ end
45
+ }
46
+ }
47
+ end
48
+
49
+ attr_accessor :natures, :builders, :classpath_containers
50
+
51
+ end
52
+
53
+ attr_reader :id, :eclipse
54
+
55
+ def initialize(id)
56
+ @id = id
57
+ @eclipse = EclipseOptions.new
58
+ end
59
+
60
+ # Returns true if the nature applies to the project
61
+ def applies(project)
62
+ false
63
+ end
64
+ end
65
+
66
+ module Nature #:nodoc:
67
+
68
+ # The natures registry
69
+ # This class works as a singleton and contains all the available natures.
70
+ #
71
+ module Registry
72
+
73
+ @registered_natures = Array.new
74
+
75
+ # Adds a nature to the registry.
76
+ # Raises exception if the object provided isn't a Nature
77
+ # or if a Nature instance is already registered with the same id.
78
+ def add_nature(nature, before = nil)
79
+ raise "#{nature} is not a nature!" if (!nature.is_a? DefaultNature)
80
+ raise "A nature with the same id is already present" if (get(nature.id))
81
+ if before.nil?
82
+ @registered_natures << nature
83
+ else
84
+ @registered_natures = @registered_natures.insert(@registered_natures.index(get(before)), nature)
85
+ end
86
+ end
87
+
88
+ # Returns a nature, from its id.
89
+ def get(nature)
90
+ if (nature.is_a? Symbol) then
91
+ @registered_natures.each {|n|
92
+ return n if (n.id == nature)
93
+ }
94
+ elsif (nature.is_a? String) then
95
+ @registered_natures.each {|n|
96
+ return n if (n.id.to_s == nature)
97
+ }
98
+ end
99
+ nil
100
+ end
101
+
102
+ # Returns all available natures
103
+ def all()
104
+ return @registered_natures.dup;
105
+ end
106
+
107
+ module_function :all, :get, :add_nature
108
+ end
109
+
110
+ module NatureExtension
111
+ include Extension
112
+ # Gives the natures defined on the project
113
+ # and the ones that apply on the project.
114
+ def applicable_natures()
115
+ Registry.all().select {|n| (natures.include?(n.id)) || n.applies(self)}
116
+ end
117
+
118
+ # :call-seq:
119
+ # natures => [:n1, :n2]
120
+ #
121
+ # Returns the project's natures.
122
+ #
123
+ # If no natures are defined on the project, the project will look for the
124
+ # natures defined in the parent's project and return them instead.
125
+ #
126
+ def natures
127
+ if @natures.nil?
128
+ if parent
129
+ @natures = parent.natures
130
+ else
131
+ @natures = []
132
+ end
133
+ end
134
+ @natures
135
+ end
136
+
137
+ protected
138
+
139
+ # :call-seq:
140
+ # natures = [n1, n2]
141
+ #
142
+ # Sets the project's natures. Allows you to specify natures by calling
143
+ # this accessor, or with the :natures property when calling #define.
144
+ #
145
+ # You can only set the natures once for a given project.
146
+ def natures=(natures)
147
+ raise 'Cannot set natures twice, or after reading its value' if @natures
148
+ @natures = (natures.is_a? Array) ? natures : [natures]
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ class Buildr::Project
155
+ include Buildr::Nature::NatureExtension
156
+ end
@@ -0,0 +1,32 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module Buildr
17
+ class OSGiNature < DefaultNature
18
+
19
+ def initialize()
20
+ super(:osgi)
21
+ eclipse.natures = "org.eclipse.pde.PluginNature"
22
+ eclipse.builders = ["org.eclipse.pde.ManifestBuilder", "org.eclipse.pde.SchemaBuilder"]
23
+ eclipse.classpath_containers = "org.eclipse.pde.core.requiredPlugins"
24
+ end
25
+
26
+ def applies(project)
27
+ ((File.exists? project.path_to("plugin.xml")) || (File.exists? project.path_to("OSGI-INF")))
28
+ end
29
+ end
30
+
31
+ Nature::Registry.add_nature(OSGiNature.new, :java)
32
+ end
@@ -0,0 +1,32 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module Buildr
17
+ class ScalaNature < DefaultNature
18
+
19
+ def initialize()
20
+ super(:scala)
21
+ eclipse.natures = ["ch.epfl.lamp.sdt.core.scalanature", "org.eclipse.jdt.core.javanature"]
22
+ eclipse.builders = "ch.epfl.lamp.sdt.core.scalabuilder"
23
+ eclipse.classpath_containers = ["ch.epfl.lamp.sdt.launching.SCALA_CONTAINER", "org.eclipse.jdt.launching.JRE_CONTAINER"]
24
+ end
25
+
26
+ def applies(project)
27
+ File.exists? project.path_to(:src, :main, :scala)
28
+ end
29
+ end
30
+
31
+ Nature::Registry.add_nature(ScalaNature.new, :java)
32
+ end
@@ -0,0 +1,23 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'buildr4osgi/nature/nature'
17
+ require 'buildr4osgi/nature/eclipse'
18
+ require 'buildr4osgi/nature/java'
19
+ require 'buildr4osgi/nature/scala'
20
+ require 'buildr4osgi/nature/osgi'
21
+
22
+
23
+
@@ -0,0 +1,275 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ module OSGi #:nodoc:
17
+
18
+ OSGI_GROUP_ID = "osgi"
19
+
20
+ # :nodoc:
21
+ # Module extending projects
22
+ # to find which matches criterias used
23
+ # to find bundles.
24
+ #
25
+ module BundleProjectMatcher
26
+
27
+ # Find if the project matches a specific set of criteria passed as parameter
28
+ # The criteria are tested against the manifest of the project, using its bundle packages manifest options and the MANIFEST.MF master file.
29
+ #
30
+ # Returns true if at least one of the packages defined by this project match the criteria.
31
+ #
32
+ def matches(criteria = {:name => "", :version => "", :exports_package => "", :fragment_for => ""})
33
+ if File.exists?(File.join(base_dir, "META-INF", "MANIFEST.MF"))
34
+ manifest = ::Buildr::Packaging::Java::Manifest.new(File.join(base_dir, "META-INF", "MANIFEST.MF"))
35
+ end
36
+ manifest ||= ::Buildr::Packaging::Java::Manifest.new()
37
+ project.packages.select {|package| package.is_a? ::OSGi::BundlePackaging}.each {|p|
38
+ package_manifest = manifest.dup
39
+ package_manifest.main.merge!(p.manifest) if p.manifest
40
+ package_manifest = Manifest.read(package_manifest.to_s)
41
+ if criteria[:exports_package]
42
+ if criteria[:version]
43
+ matchdata = package_manifest.first[Bundle::B_EXPORT_PKG][criteria[:exports_package]] unless package_manifest.first[Bundle::B_EXPORT_PKG].nil?
44
+ return false unless matchdata
45
+ exported_package_version = matchdata["version"]
46
+ if criteria[:version].is_a? VersionRange
47
+ return criteria[:version].in_range(exported_package_version)
48
+ else
49
+ return criteria[:version] == exported_package_version
50
+ end
51
+ else
52
+ return false if package_manifest.first[Bundle::B_EXPORT_PKG].nil?
53
+ return !package_manifest.first[Bundle::B_EXPORT_PKG][criteria[:exports_package]].nil?
54
+ end
55
+ elsif (package_manifest.first[Bundle::B_NAME].keys.first == criteria[:name] || id == criteria[:name])
56
+
57
+ if criteria[:version]
58
+ if criteria[:version].is_a?(VersionRange)
59
+ return criteria[:version].in_range(version)
60
+ else
61
+ return criteria[:version] == version
62
+ end
63
+ else
64
+ # depending just on the name, returning true then.
65
+ return true
66
+ end
67
+ end
68
+ }
69
+ return false
70
+ end
71
+
72
+ end
73
+
74
+ # A bundle is an OSGi artifact represented by a jar file or a folder.
75
+ # It contains a manifest file with specific OSGi headers.
76
+ #
77
+ class Bundle
78
+ include Buildr::ActsAsArtifact
79
+
80
+ #Keys used in the MANIFEST.MF file
81
+ B_NAME = "Bundle-SymbolicName"
82
+ B_REQUIRE = "Require-Bundle"
83
+ B_IMPORT_PKG = "Import-Package"
84
+ B_EXPORT_PKG = "Export-Package"
85
+ B_FRAGMENT_HOST = "Fragment-Host"
86
+ B_VERSION = "Bundle-Version"
87
+ B_DEP_VERSION = "bundle-version"
88
+ B_RESOLUTION = "resolution"
89
+ B_LAZY_START = "Bundle-ActivationPolicy"
90
+ B_OLD_LAZY_START = "Eclipse-LazyStart"
91
+
92
+ # Creates a bundle out of a project, using the manifest defined in its bundle package
93
+ # and the MANIFEST.MF file present in the project if any.
94
+ def self.fromProject(project)
95
+ packaging = project.packages.select {|package| package.is_a?(::OSGi::BundlePackaging)}
96
+ raise "More than one bundle packaging is defined over the project #{project.id}, see BOSGI-16." if packaging.size > 1
97
+ return nil if packaging.empty?
98
+ manifest = ::Buildr::Packaging::Java::Manifest.new(File.exists?("META-INF/MANIFEST.MF") ? File.read("META-INF/MANIFEST.MF") : nil)
99
+ manifest.main.merge!(project.manifest)
100
+ manifest.main.merge!(packaging.first.manifest)
101
+ fromManifest(Manifest.read(manifest.to_s), packaging.first.to_s)
102
+ end
103
+
104
+ # Creates itself by loading from the manifest file passed to it as a hash
105
+ # Finds the name and version, and populates a list of dependencies.
106
+ def self.fromManifest(manifest, jarFile)
107
+ if manifest.first[B_NAME].nil?
108
+ warn "Could not find the name of the bundle represented by #{jarFile}"
109
+ return nil
110
+ end
111
+
112
+ #see http://aspsp.blogspot.com/2008/01/wheressystembundlejarfilecont.html for the system.bundle trick.
113
+ #key.strip: sometimes there is a space between the comma and the name of the bundle.
114
+ #Add the required bundles:
115
+ bundles = []
116
+ manifest.first[B_REQUIRE].each_pair {|key, value| bundles << Bundle.new(key.strip, value[B_DEP_VERSION], {:optional => value[B_RESOLUTION] == "optional"}) unless "system.bundle" == key} unless manifest.first[B_REQUIRE].nil?
117
+ exports = []
118
+ manifest.first[B_EXPORT_PKG].each_pair {|key, value| exports << BundlePackage.new(key.strip, value["version"])} unless manifest.first[B_EXPORT_PKG].nil?
119
+
120
+ #Parse the version
121
+ version = manifest.first[B_VERSION].nil? ? nil : manifest.first[B_VERSION].keys.first
122
+
123
+ #Read the imports
124
+ imports = []
125
+ manifest.first[B_IMPORT_PKG].each_pair {|key, value| imports << BundlePackage.new(key.strip, value["version"], :is_export => false)} unless manifest.first[B_IMPORT_PKG].nil?
126
+
127
+ #Read the imported packages
128
+
129
+ bundle = Bundle.new(manifest.first[B_NAME].keys.first, version, {:file => jarFile, :bundles => bundles, :imports => imports, :exported_packages => exports})
130
+ if !manifest.first[B_LAZY_START].nil?
131
+ # We look for the value of BundleActivationPolicy: lazy or nothing usually.
132
+ # lazy may be spelled Lazy too apparently, so we downcase the string in case.
133
+ bundle.lazy_start = "lazy" == manifest.first[B_LAZY_START].keys.first.strip.downcase
134
+ else
135
+ bundle.lazy_start = "true" == manifest.first[B_OLD_LAZY_START].keys.first.strip unless manifest.first[B_OLD_LAZY_START].nil?
136
+ end
137
+ if (bundle.lazy_start)
138
+ bundle.start_level = 4
139
+ else
140
+ bundle.start_level = 1
141
+ end
142
+
143
+ bundle.fragment = Bundle.new(manifest.first[B_FRAGMENT_HOST].keys.first.strip,
144
+ manifest.first[B_FRAGMENT_HOST].values.first[B_DEP_VERSION]) unless (manifest.first[B_FRAGMENT_HOST].nil?)
145
+ return bundle
146
+ end
147
+
148
+
149
+
150
+ # Attributes of a bundle, derived from its manifest
151
+ # The name is always the symbolic name
152
+ # The version is either the exact version of the bundle or the range in which the bundle would be accepted.
153
+ # The file is the location of the bundle on the disk
154
+ # The optional tag is present on bundles resolved as dependencies, marked as optional.
155
+ # The start level is deduced from the bundles.info file. Default is 1.
156
+ # The lazy start is found in the bundles.info file
157
+ # group is the artifact group used for Maven. By default it is set to OSGI_GROUP_ID.
158
+ # fragment is a Bundle object that represents the fragment host of this bundle (which means this bundle is a fragment if this field is not null).
159
+ # exported_packages is an array of strings representing the packages exported by the bundle.
160
+ # imports is an array of BundlePackage objects representing the packages imported by the bundle.
161
+ attr_accessor :name, :version, :bundles, :file, :optional, :start_level, :lazy_start, :group, :fragment, :exported_packages, :imports
162
+
163
+ alias :id :name
164
+
165
+ def initialize(name, version, args = {:file => nil, :bundles=>[], :imports => [], :optional => false}) #:nodoc:
166
+ @name = name
167
+ @version = VersionRange.parse(version) || (version.nil? ? nil : Version.new(version))
168
+ @bundles = args[:bundles] || []
169
+ @imports = args[:imports] || []
170
+ @exported_packages = args[:exported_packages] || []
171
+ @file = args[:file]
172
+ @optional = args[:optional]
173
+ @start_level = 4
174
+ @type = "jar" #it's always a jar, even if it is a directory: we will jar it for Maven.
175
+ @group = OSGI_GROUP_ID
176
+ end
177
+
178
+
179
+ #
180
+ # Resolves the matching artifacts associated with the project.
181
+ #
182
+ def resolve_matching_artifacts(project)
183
+ # Collect the bundle projects, duplicate them so no changes can be applied to them
184
+ # and extend them with the BundleProjectMatcher module
185
+
186
+ b_projects = OSGi::BundleProjects::bundle_projects.select {|p|
187
+ unless p == project
188
+ p.extend BundleProjectMatcher
189
+ p.matches(:name => name, :version => version)
190
+ end
191
+ }
192
+ #projects take precedence over the dependencies elsewhere, that's what happens in Eclipse
193
+ # for example
194
+ return b_projects unless b_projects.empty?
195
+ return project.osgi.registry.resolved_containers.collect {|i|
196
+ i.find(:name => name, :version => version)
197
+ }.flatten.compact.collect{|b| b.dup }
198
+ end
199
+
200
+ # Returns true if the bundle is an OSGi fragment.
201
+ #
202
+ def fragment?
203
+ !fragment.nil?
204
+ end
205
+
206
+ def to_s #:nodoc:
207
+ to_spec()
208
+ end
209
+
210
+ def to_yaml(opts = {}) #:nodoc:
211
+ to_s.to_yaml(opts)
212
+ end
213
+
214
+ def <=>(other) #:nodoc:
215
+ if other.is_a?(Bundle)
216
+ return to_s <=> other.to_s
217
+ else
218
+ return to_s <=> other
219
+ end
220
+ end
221
+
222
+ # Resolve a bundle from itself, by finding the appropriate bundle in the OSGi containers.
223
+ # Returns self or the project it represents if a project is found to be self.
224
+ #
225
+ def resolve(project, bundles = resolve_matching_artifacts(project))
226
+ bundle = case bundles.size
227
+ when 0 then nil
228
+ when 1 then bundles.first
229
+ else
230
+ OSGi::BundleResolvingStrategies.send(project.osgi.options.bundle_resolving_strategy, bundles)
231
+ end
232
+ if bundle.nil?
233
+ warn "Could not resolve bundle for #{self.to_s}"
234
+ return nil
235
+ end
236
+ return bundle if bundle.is_a?(Buildr::Project)
237
+
238
+ osgi = self.dup
239
+ osgi.name = bundle.name
240
+ osgi.version = bundle.version
241
+ osgi.bundles = bundle.bundles
242
+ osgi.file = bundle.file
243
+ osgi.optional = bundle.optional
244
+ osgi.start_level = bundle.start_level
245
+ osgi.group = bundle.group
246
+
247
+ osgi
248
+ end
249
+
250
+ # Finds the fragments associated with this bundle.
251
+ #
252
+ def fragments(project)
253
+ project.osgi.registry.resolved_containers.collect {|i|
254
+ i.find_fragments(:host => name).select{|f|
255
+ if f.fragment.version.is_a? VersionRange
256
+ f.fragment.version.in_range(version)
257
+ elsif f.fragment.version.nil?
258
+ true
259
+ else
260
+ f.fragment.version == version
261
+ end
262
+ }
263
+ }.flatten.compact.collect{|b| b.dup }
264
+ end
265
+
266
+ # Compares with another bundle and returns true if the name and version match.
267
+ def ==(other) #:nodoc:
268
+ return false unless other.is_a?(Bundle)
269
+ name == other.name && version == other.version
270
+ end
271
+
272
+ alias :eql? ==
273
+
274
+ end
275
+ end