Return-Path: Delivered-To: apmail-buildr-commits-archive@www.apache.org Received: (qmail 86811 invoked from network); 4 Dec 2010 09:30:17 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 4 Dec 2010 09:30:17 -0000 Received: (qmail 50882 invoked by uid 500); 4 Dec 2010 09:30:17 -0000 Delivered-To: apmail-buildr-commits-archive@buildr.apache.org Received: (qmail 50855 invoked by uid 500); 4 Dec 2010 09:30:17 -0000 Mailing-List: contact commits-help@buildr.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@buildr.apache.org Delivered-To: mailing list commits@buildr.apache.org Received: (qmail 50848 invoked by uid 99); 4 Dec 2010 09:30:17 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 04 Dec 2010 09:30:17 +0000 X-ASF-Spam-Status: No, hits=-1999.7 required=10.0 tests=ALL_TRUSTED,URIBL_RHS_DOB X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 04 Dec 2010 09:30:11 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id F1A792388903; Sat, 4 Dec 2010 09:28:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1042121 - in /buildr/trunk: CHANGELOG addon/buildr/bnd.rb doc/packaging.textile spec/addon/bnd_spec.rb spec/sandbox.rb Date: Sat, 04 Dec 2010 09:28:37 -0000 To: commits@buildr.apache.org From: donaldp@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20101204092837.F1A792388903@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: donaldp Date: Sat Dec 4 09:28:37 2010 New Revision: 1042121 URL: http://svn.apache.org/viewvc?rev=1042121&view=rev Log: BUILDR-554 - Add support for OSGi bundle packages by importing the buildr_bnd plugin Added: buildr/trunk/addon/buildr/bnd.rb buildr/trunk/spec/addon/bnd_spec.rb Modified: buildr/trunk/CHANGELOG buildr/trunk/doc/packaging.textile buildr/trunk/spec/sandbox.rb Modified: buildr/trunk/CHANGELOG URL: http://svn.apache.org/viewvc/buildr/trunk/CHANGELOG?rev=1042121&r1=1042120&r2=1042121&view=diff ============================================================================== --- buildr/trunk/CHANGELOG (original) +++ buildr/trunk/CHANGELOG Sat Dec 4 09:28:37 2010 @@ -1,4 +1,6 @@ 1.4.5 (Pending) +* Added: BUILDR-554 Add support for OSGi bundle packages by importing the + buildr_bnd plugin * Added: BUILDR-125 Add support for in application.xml of EAR packaging (Mikael Amborn) * Added: BUILDR-550 Add support for groovydoc Added: buildr/trunk/addon/buildr/bnd.rb URL: http://svn.apache.org/viewvc/buildr/trunk/addon/buildr/bnd.rb?rev=1042121&view=auto ============================================================================== --- buildr/trunk/addon/buildr/bnd.rb (added) +++ buildr/trunk/addon/buildr/bnd.rb Sat Dec 4 09:28:37 2010 @@ -0,0 +1,132 @@ +module Buildr + module Bnd + class << self + # The specs for requirements + def dependencies + ["biz.aQute:bnd:jar:0.0.384"] + end + + # Repositories containing the requirements + def remote_repository + "http://www.aQute.biz/repo" + end + + def bnd_main(*args) + cp = Buildr.artifacts(self.dependencies).each(&:invoke).map(&:to_s) + Java::Commands.java 'aQute.bnd.main.bnd', *(args + [{ :classpath => cp }]) + end + end + + class BundleTask < Rake::FileTask + attr_reader :project + attr_accessor :classpath + + def [](key) + @params[key] + end + + def []=(key, value) + @params[key] = value + end + + def classpath_element(dependencies) + artifacts = Buildr.artifacts([dependencies]) + self.prerequisites << artifacts + artifacts.each do |dependency| + self.classpath << dependency.to_s + end + end + + def to_params + params = self.project.manifest.merge(@params).reject { |k, v| v.nil? } + params["-classpath"] ||= self.classpath.collect(&:to_s).join(", ") + params['Bundle-SymbolicName'] ||= [self.project.group, self.project.name.gsub(':', '.')].join('.') + params['Bundle-Name'] ||= self.project.comment || self.project.name + params['Bundle-Description'] ||= self.project.comment + params['Bundle-Version'] ||= self.project.version + if params["Include-Resource"].nil? && !project.resources.target.nil? + params["Include-Resource"] = "#{project.resources.target}/" + end + params['-removeheaders'] ||= "Include-Resource,Bnd-LastModified,Created-By,Implementation-Title,Tool" + + params + end + + def project=(project) + @project = project + end + + def classpath=(classpath) + @classpath = [] + Buildr.artifacts([classpath.flatten.compact]).each do |dependency| + self.prerequisites << dependency + @classpath << dependency.to_s + end + @classpath + end + + def classpath + @classpath ||= ([project.compile.target] + project.compile.dependencies).flatten.compact + end + + protected + + def initialize(*args) #:nodoc: + super + @params = {} + enhance do + filename = self.name + # Generate BND file with same name as target jar but different extension + bnd_filename = filename.sub /(\.jar)?$/, '.bnd' + + params = self.to_params + params["-output"] = filename + File.open(bnd_filename, 'w') do |f| + f.print params.collect { |k, v| "#{k}=#{v}" }.join("\n") + end + + Buildr::Bnd.bnd_main( "build", "-noeclipse", bnd_filename ) + begin + Buildr::Bnd.bnd_main( "print", "-verify", filename ) + rescue => e + rm filename + raise e + end + end + end + end + + module ProjectExtension + include Extension + + first_time do + desc "Does `bnd print` on the packaged bundle and stdouts the output for inspection" + Project.local_task("bnd:print") + end + + def package_as_bundle(filename) + project.task('bnd:print' => [filename]) do |task| + Buildr::Bnd.bnd_main("print", filename) + end + + dirname = File.dirname(filename) + directory(dirname) + + # Add Buildr.application.buildfile so it will rebuild if we change settings + task = BundleTask.define_task(filename => [Buildr.application.buildfile, dirname]) + task.project = self + # the last task is the task considered the packaging task + task + end + + # Change the bundle package to .jar extension + def package_as_bundle_spec(spec) + spec.merge(:type => :jar) + end + end + end +end + +class Buildr::Project + include Buildr::Bnd::ProjectExtension +end \ No newline at end of file Modified: buildr/trunk/doc/packaging.textile URL: http://svn.apache.org/viewvc/buildr/trunk/doc/packaging.textile?rev=1042121&r1=1042120&r2=1042121&view=diff ============================================================================== --- buildr/trunk/doc/packaging.textile (original) +++ buildr/trunk/doc/packaging.textile Sat Dec 4 09:28:37 2010 @@ -337,6 +337,180 @@ package(:ear).security_roles << {:id=>'S :description=>'Super user', :name=>'superCoolUser'} {% endhighlight %} +h2(#bundle). Packaging OSGi Bundles + +OSGi bundles are jar files with additional metadata stored in the manifest. Buildr uses an external tool "Bnd":http://www.aqute.biz/Code/Bnd to create the package. Directives and properties can be explicitly passed to the build tool and buildr will provide reasonable defaults for properties that can be derived from the project model. Please see the bnd tool for documentation on the available properties. + +The bundle packaging format is included as an addon so the build file must explicitly require the addon using using require "buildr/bnd" and must add a remote repository from which the bnd can be downloaded. A typical project that uses the bundle packaging addon may look something like; + +{% highlight ruby %} +require "buildr/bnd" + +repositories.remote << Buildr::Bnd.remote_repository + +define 'myProject' do + ... + package(:bundle).tap do |bnd| + bnd['Import-Package'] = "*;resolution:=optional" + bnd['Export-Package'] = "*;version=#{version}" + end + ... +end +{% endhighlight %} + +The @[]@ method on the bundle package is used to provide directives to the bnd tool that are not inherited by sub-projects while the standard 'manifest' setting is used to define properties that inherited by sub-projects. + +h3. Defaults + +The addon sets the following bnd parameters; + +* "Bundle-Version" defaults to the project version. +* "Bundle-SymbolicName" defaults to the concatenation of the project group and project id, replacing ':' characters with '.'. +* "Bundle-Name" defaults to the project description if present else the project name +* "Bundle-Description" defaults to the project description. +* "-classpath" is set to the compile target directory and any compile time dependencies. +* "Include-Resource" defaults to the dir project.resources.target if it exists. + +h3. Parameters + +h4. classpath_element + +The user can also specify additional elements that are added to the classpath using the 'classpath_element' method. If the parameter to this element is a task, artifact, artifact namespace etc. then it will be resolved prior to invoking bnd. + +{% highlight ruby %} +... +define 'foo' do + ... + package(:bundle).tap do |bnd| + # This dependency will be added to classpath + bnd.classpath_element 'someOtherExistingFile.zip' + # All of these dependencies will be invoked and added to classpath + bnd.classpath_element artifact('com.sun.messaging.mq:imq:jar:4.4') + bnd.classpath_element project('bar') # Adds all the packages + bnd.classpath_element 'org.apache.ant:ant:jar:1.8.0' + bnd.classpath_element file('myLocalFile.jar') + ... + end + + project 'bar' do + ... + end +end +{% endhighlight %} + +h4. classpath + +The user can specify the complete classpath using the 'classpath' method. The classpath should be an array of elements. If the element is a task, artifact, artifact namespace etc. then it will be resolved prior to invoking bnd. + +{% highlight ruby %} +... +define 'foo' do + ... + package(:bundle).tap do |bnd| + bnd.classpath [ project.compile.target, + 'someOtherExistingFile.zip', + artifact('com.sun.messaging.mq:imq:jar:4.4'), + project('bar'), + 'org.apache.ant:ant:jar:1.8.0', + file('myLocalFile.jar') ] + ... + end + + project 'bar' do + ... + end +end +{% endhighlight %} + +h3. Examples + +h4. Including non-class resources in a bundle + +Bnd can be used to include non-class resources in a bundle. The following example includes all resources in 'src/etc' into the bundle. + +{% highlight ruby %} +define 'myproject' do + ... + package(:bundle).tap do |bnd| + bnd['Include-Resource'] = project._('src/etc') + '/' + ... + end +end +{% endhighlight %} + +h4. Using bnd to wrap an existing jar + +Bnd can be used to wrap an existing jar as an OSGi bundle. The following example wraps the OpenMQ JMS provider as an OSGi bundle. + +{% highlight ruby %} +... +# Add repository for OpenMQ +repositories.remote << 'http://download.java.net/maven/2' + +desc 'OSGi bundle for OpenMQ JMS provider client library' +define 'com.sun.messaging.mq.imq' do + project.version = '4.4' + project.group = 'iris' + package(:bundle).tap do |bnd| + bnd['Import-Package'] = "*;resolution:=optional" + bnd['Export-Package'] = "com.sun.messaging.*;version=#{version}" + bnd.classpath_element 'com.sun.messaging.mq:imq:jar:4.4' + end +end +{% endhighlight %} + +h4. Create an OSGi bundle with an Activator + +The following example presents a basic buildfile for building an OSGi bundle with an activator. + +{% highlight ruby %} +... +# repository for OSGi core bundle +repositories.remote << 'https://repository.apache.org/content/repositories/releases' + +desc 'Hello World bundle' +define 'helloworld' do + project.version = '1.0' + project.group = 'org.example' + compile.with 'org.apache.felix:org.osgi.core:jar:1.4.0' + package(:bundle).tap do |bnd| + bnd['Export-Package'] = "org.example.helloworld.api.*;version=#{version}" + bnd['Bundle-Activator'] = "org.example.helloworld.Activator" + end +end +{% endhighlight %} + +h4. Inheriting parameters for bnd tool + +The following example shows how you can use 'manifest' to define a bnd parameter that is inherited by all child sub-projects. The "Bundle-License" defined in the top level project is passed to the bnd tool when generating both the 'fe' and 'fi' sub-projects but the 'fo' sub-project overrides this parameter with a local value. + +{% highlight ruby %} +... +define 'myproject' do + manifest['Bundle-License'] = "http://www.apache.org/licenses/LICENSE-2.0" + ... + define 'fe' do + ... + package(:bundle).tap do |bnd| + ... + end + end + + define 'fi' do + ... + package(:bundle).tap do |bnd| + ... + end + end + + define 'fo' do + ... + package(:bundle).tap do |bnd| + bnd['Bundle-License'] = "http://www.apache.org/licenses/LICENSE-1.1" + end + end +end +{% endhighlight %} h2(#tar). Packaging Tars and GZipped Tars Added: buildr/trunk/spec/addon/bnd_spec.rb URL: http://svn.apache.org/viewvc/buildr/trunk/spec/addon/bnd_spec.rb?rev=1042121&view=auto ============================================================================== --- buildr/trunk/spec/addon/bnd_spec.rb (added) +++ buildr/trunk/spec/addon/bnd_spec.rb Sat Dec 4 09:28:37 2010 @@ -0,0 +1,330 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with this +# work for additional information regarding copyright ownership. The ASF +# licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + + +require File.expand_path('../spec_helpers', File.dirname(__FILE__)) +Sandbox.require_optional_extension 'buildr/bnd' + +def open_zip_file(file = 'target/foo-2.1.3.jar') + jar_filename = @foo._(file) + File.should be_exist(jar_filename) + Zip::ZipFile.open(jar_filename) do |zip| + yield zip + end +end + +def open_main_manifest_section(file = 'target/foo-2.1.3.jar') + jar_filename = @foo._(file) + File.should be_exist(jar_filename) + yield Buildr::Packaging::Java::Manifest.from_zip(jar_filename).main +end + +describe Buildr::Bnd do + + describe "package :bundle" do + describe "with a valid bundle" do + before do + write "src/main/java/com/biz/Foo.java", <