Jump to: navigation, search

Introduction to Buckminster

Revision as of 20:05, 14 February 2009 by Henrik.lindberg.cloudsmith.com (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

< To: Buckminster Project


Getting Started

The purpose of this document is to enable you to install Buckminster, and to start using it for materializing and publishing component specifications. It provides samples of Buckminster code as XML fragments, and illustrates common usage scenarios.

If you are new to Buckminster, then you should read the Why Buckminster? document first.

The key essential concepts used in Buckminster are:

  • A Component Query (CQUERY). A CQUERY is a (usually quite small) XML file which names some component that you want to download and materialise. Included within the CQUERY is a reference (usually a URL) to a resource map (RMAP).
  • A Resource Map (RMAP). An RMAP (again, an XML file) identifies possible locations - e.g. internet repositories - where a component - given in a CQUERY - can be found. The component in the CQUERY may depend on having further components (which in turn may need further ones, forming a transitive closure): the RMAP lists all the places where all of the components may be found.
  • A publisher of components normally provides his/her audience of consumers with a CQUERY and RMAP. Armed with these, consumers can give the CQUERY (which in turn points to the given RMAP) to the Buckminster plugin to the Eclipse IDE and the appropriate components will be materialised into Eclipse. Materialisation into non-Eclipse environments, including stand-alone on a local or remote machine, is also possible.
  • Bills of Materials (BOM). A BOM is (an XML file) generated automatically by Buckminster, given a CQUERY and accompanying RMAP: it gives a detailed list of all components, and their respective locations, in order to fulfill that particular CQUERY. A BOM file can also be published and used to materialise, in situations where the publisher wants to ensure that all of his/her audience of consumers get precisely the same set of specific component instances from the same set of repositories.
  • Component Specification (CSPEC). A CSPEC (is an XML file and) describes the metadata, including dependencies on other components, for a particular component. CSPECs are automatically generated by Buckminster for Eclipse plugins and features, and thus Eclipse-based publishers in most cases do not need to manually write CSPECs.
  • Component Specification Extension (CSPEX). A CSPEX (is an XML file and) is manually written to extend an automatically generated CSPEC in cases where Buckminster cannot find the entire metadata needed automatically.
  • Materialisation Specification (MSPEC). An MSPEC (is an XML file which) can be provided by a publisher to ensure that downloaded components materialise to particular folders/directories on target machines, and with appropriate replace/update/discard policies if some of the components are in fact already downloaded on a specific machine.

All these Buckminster features are explained in this document, using working examples. However keep in mind that in many cases, a CQUERY and an RMAP are all that are needed..

Installation

Installation instructions for Buckminster into the Eclipse IDE are given here.

What do you want to do?

There are a number of different ways in which you may wish to use Buckminster, and these are listed in each of the following sections:





Materialize an existing component

A materialization is started in either of two ways:

  • by using a Component Query (CQUERY) – for the top most component required OR
  • by providing a pre-existing Bill of Materials (BOM)

The CQUERY case is described here. The BOM case is in the immediate next section.


A sample CQUERY is online here, from the Hello World example, and reproduced below for convenience:

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0"
    resourceMap="http://www.eclipse.org/buckminster/samples/rmaps/demo.rmap">
    <cq:rootRequest name="org.demo.hello.xml.world" componentType="osgi.bundle" versionType="OSGi"/>
</cq:componentQuery>

The first line indicates that the file contains XML.

The second line gives a CQUERY (from the XML name space http://www.eclipse.org/buckminster/CQuery-1.0) and also identifies a Resource Map (or RMAP). RMAPs are discussed later below. The resourceMap entry may in fact be omitted, in which case Buckminster will attempt to resolve the CQUERY locally or by using preconfigured remote resolvers.

The rootRequest identifies the name of the top most component required – here org.demo.hello.xml.world. The (optional) componentType identifies this component as a osgi.bundle (an Eclipse plugin). Finally the versionType indicates that the version numbering scheme used for this particular component follows the OSGi versioning convention. This is in fact the default version scheme for Buckminster, and an OSGI formatted version string follows the pattern [0-9].[0-9].[0-9].[a-zA-Z0-9_-] (for example: 3.2.0.RC_beta-1). Alternative values for the versionType are String; Timestamp; or Triplet. An overview of versioning is given Why Buckminster? introduction and there is a fuller description in the Buckminster meta-data language guide.


You can find the CQUERY wizard to help you write CQUERY XML files in File > New > Other > Buckminster > Component Query File. Enter an appropriate Container and File name in which you want your new CQUERY to be placed. Then fill in the fields of the form as needed:

  • the Component Name is the top level name of your target component, and will be the rootRequest for the CQUERY
  • Properties and Advisor Nodes (see the tabbed form at the bottom of the pane) are advanced topics, discussed TBD
  • An RMAP should normally be given. We discuss this in a later section below.

At the bottom of the wizard, there are three buttons: select External Save As to save your CQUERY as an external file.


To actually execute a CQUERY:

  • either select File > Open File within in the Eclipse Java SDK, and enter the URL for the CQUERY in the File Name field. This will then start the CQUERY wizard and populate it with the data from the CQUERY file you specified OR
  • use the CQUERY wizard directly OR
  • use File > Import > Other > Materialize from Buckminster MSPEC, CQUERY or BOM, pressing Next and then the URL for the CQUERY and the Load button.

In each case, proceed to select the Resolve to Wizard or, more directly, Resolve and Materialise button. Resolve to Wizard allows you a finer degree of control. In particular, it can show you the full set of components that Buckminster has resolved and is prepared to materialize, as well as letting you save the derived BOM (i.e., as an external file). Press Next and the platform environment settings can be examined, and the generated MSPEC saved if you so wish. Press Finish to execute the materialisation.

When materialization starts, a new window will open, entitled Resolving Query, with a progress bar. Buckminster runs the query, transitively finds all the required components, downloads them, and runs all required actions (such as building the required jar). When Buckminster has successfully finished, your workspace is set up with the transitive closure of the components selected.


So, in summary, to initiate a materialization:

  1. Write a CQUERY in XML into a file, either directly using an editor or by using the CQUERY wizard.
  2. State the name of the top level component you are materializing.
  3. Provide the URL of the RMAP you want to use to identify one or more repositories where you expect to find the top level component, and any transitively required dependencies, to be located.
  4. Enter the file name of your CQUERY file into File > Open File in Eclipse, or immediately proceed to resolve and materialise within the CQUERY wizard.







Materializing using a pre-existing Bill Of Materials

As noted in the Why Buckminster? guide, a BOM represents a snapshot of your components taken at the time of resolution when the BOM was externalised from Buckminster's internal model. The same query, resolved later at a different time, may yield a different result (i.e. a different BOM) because components may have moved or newer versions may be available.

It can be useful to use a BOM (rather than a CQUERY) for materialization, when it is important that every user materializes the identical configuration. Examples include sharing a software configuration within a team, or submitting a configuration for testing.

As noted in the previous section, a BOM can be saved as an external file by the CQUERY wizard and before materialization using the BOM function in the Resolve to Wizard.

Subsequently, the BOM file can be used by selecting File > Import > Other > Materialize from Buckminster MSPEC, CQUERY or BOM; pressing Next; then the URL for the BOM file, and finally the Load button. Note that if instead you simply pass a BOM file to File > New File, the BOM file will be displayed as a text file.

After the BOM file is loaded, press either Finish to complete the materialization, or Next to allow finer control as in the CQUERY Resolve to Wizard (explained in the previous section), followed eventually by Finish to materialize.


After Materialisation: Where is the component on my machine ?

Once you have successfully materialised a component, you should be able to see it listed in your package explorer: Window > Show view > Package Explorer.

If you right-click the component, a menu listing things you can do with the component is thrown up. In particular, the menu includes items Buckminster > Invoke Action.. and Buckminster > View CSPEC..

Invoke Action.. allows you to click on any of the publicly available action attributes defined for this particular component. Action attributes are discussed in detail below. An optional Properties file can be also be specified as context for whatever action you select: for example, to specify the output folder for a build action.

View CPSEC.. allows you to view the Component Specification (CPSEC) for the component, which in many cases is automatically generated by Buckminster. The CSPEC will list the publicly available action attributes which Invoke Action.. can use, together with other attributes. CSPECs are discussed in detail below.





Resource Maps (RMAPs)

An RMAP provides location information for families of components. When Buckminster needs to load a particular component , it looks in the RMAP (specified in the CQUERY, see above) to determine the repository (or repositories) containing it. If that component in turn requires others components, the RMAP is consulted to find the repository (or repositories) containing each component.

This separation of component and storage location is useful because it allows Buckminster to retrieve the same component from potentially many different storage locations, allowing flexibility.

First, the RMAP defines storage locations for families of components, rather than single components. A user can say, "find all the Apache components on the Apache ftp server," without having to specify "find Apache Struts on the Apache ftp server and find Apache Cocoon on the Apache ftp server and find ...," etc., etc. This is done by locator string patterns, as discussed below.

Second, the RMAP defines a search path of storage locations to search for a component. A user can say, "first look in my local repository, then look in my team's repository, then look in my corporate group repository, then look in the Eclipse public CVS repository". This is done by providing alternative repository providers within a searchPath, as we will see below.

Third, the RMAP allows variability by setting alternative values for the locators. For example, alternative repositories can be specified for different distributed development sites. The RMAP for a team in Stockholm would list the same component families as the RMAP for a team in Winnipeg, but the two RMAPs would differ with alternative local repository servers (specified in their respective locator entries). TCP round-trips from Canada to Sweden are slower than TCP round-trips from Canada to Canada, so the Winnipeg team might maintain a replicated CVS repository for certain components. Buckminster allows both teams to use essentially the same RMAP, but to define a different repository sites, and thus a different set of search paths. Because Buckminster tries each entry in a list of locators in order, the last locator entry in the alternative RMAPs might be the same: for example, if components were not available locally in a repository cache, they would be fetched from some common designated master site for all teams.

Similarly to CQUERYs, an RMAP file can be manually prepared using an editor, or a Buckminster wizard at File > New > Other > Buckminster > Resource Map File.

Here is a simple RMAP (and is online here), from the Hello World example,:

<?xml version="1.0" encoding="UTF-8"?>
<rmap
	xmlns="http://www.eclipse.org/buckminster/RMap-1.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mp="http://www.eclipse.org/buckminster/MavenProvider-1.0"
	xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0">

	<searchPath name="default">
		<provider readerType="svn" componentTypes="eclipse.feature,osgi.bundle,buckminster" source="true">
			<uri format="svn://dev.eclipse.org/svnroot/tools/org.eclipse.buckminster/trunk/org.eclipse.buckminster/demo/{0}">
				<bc:propertyRef key="buckminster.component" />
			</uri>
		</provider>
	</searchPath>

	<locator searchPathRef="default" pattern="^org\.demo\..*" />
	<redirect href="http://www.eclipse.org/buckminster/samples/rmaps/dogfood2.rmap" pattern=".*"/>
</rmap>

The first six lines declare the name spaces and syntax of the RMAP and the repository providers needed.

Below that are two major elements declaring searchPaths: the first is called default, and the second is called maven.

Continue down and you find two locator declarations. These map patterns of component names, to specific searchPaths:

  • the first states that if a component name starts with the pattern se.tada. then the maven search path should be used; and
  • the second locator states that if a component name starts with the pattern org.demo. then the default path should be used.

Note that locator entries are tried in order: in this example, Buckminster will first try to match component names beginning with se.tada. (and if matched, then hence the maven repository), before the second entry. Thus in general, the locator list should be arranged in order from "most specific string pattern" to "least specific": in the example above the order in fact does not matter since the string patterns are distinct.

The same searchPathRef value may occur in multiple locator declarations. For example, we could add a further declaration:

    <rm:locator searchPathRef="default" pattern="^hi\.hello\..*" />

and thus components whose name started with se.tada or with hi.hello would in each case map to the maven search path.

Back to the searchPaths themselves. An RMAP can have one or more searchPaths, and the order in which they appear is not significant. Each searchPath must have one or more providers, and if more than one provider is given, they will be tried in order for that particular searchPath. In our case, we have two paths:

  1. The default path:
    1. The default path declares that the repository for these family of components (in fact, those starting with org.demo.) is in a CVS repository, and that in fact these components are part of an eclipse project ("osgi.bundle, eclipse.feature, buckminster").
    2. We do not want to commit changes back (mutable=false), and we do not want to extract source code (source=false).
    3. The URI to a specific CVS repository is then given.
    4. This URI ends with the name of the component. This name is obtained from the preset property buckminster.component which contains the name of the component being matched.
  2. The maven path:
    1. The maven path declares that it uses a maven provider; a readerType of maven, and that the componentType is also a maven component.
    2. Like the default path, we do not want to commit changes back (mutable=false), and we do not want to extract source code (source=false).
    3. A URI to the maven repository at Ibiblio is declared.
    4. A mapping that translates the component name into what the actual file on Ibiblio is called, is then declared (i.e. mapping se.tada.util.sax to tada-sax).


So, in summary, to write an RMAP:

  1. Identify a number of searchPaths which the RMAP can use.
  2. For each searchPath, give a locator string pattern matching the component names which you want to be found using this searchPath. In fact you can define several locator string patterns, so that several different sets of components can all be found using the same searchPath.
  3. For each searchPath, give one or more providers. Each provider should list its readerType (CVS, maven, subversion or whatever) together with a list of URIs at which appropriate repositories can be found.



What RMAP Reader Types are supported?

At the time of writing, the full list of readerTypes for use within provider declarations are listed in the Buckminster meta-data language guide. They include for example CVS, Subversion, Maven, Perforce and site.feature amongst others.

componentTypes are required to configure the required readerType. The componentTypes indicates to the readerType which component structure and meta-data to expect for the declared provider. This information is essential in order for Buckminster to extract component dependency information, which Buckminster automatically translates on-the-fly into its own dependency format (ie a CSPEC) which is then used in the component resolution and materialization process.

componentTypes must be referenced in this attribute by its fully qualified name. The full list of implementations of componentTypess are also given in the Buckminster meta-data language guide. They include for example osgi.bundle, eclipse.feature, jar and maven amongst others.

Publish an existing component

Buckminster provides two ways to publish an existing component:

  1. Write a CQUERY, and associated RMAP, as described above in the section Materialize an existing component above. Publish the CQUERY so that others can use it, as described also in the same section OR
  2. Derive a BOM from a CQUERY (and an associated RMAP). Publish the BOM so that others can use it, as described in Materializing using a pre-existing Bill Of Materials. Bear in mind the advantages and dis-advantages of publishing a BOM rather than a CQUERY, as described in the same section.



Publish your Eclipse project

In many cases, Buckminster can automatically fully, or partially, derive the specifications needed to "Buckminsterize" an existing project from meta-data that is already available. Since this is true for Eclipse plugins, "Buckminsterizing" these projects is particularly simple.

For Eclipse project that are not just plug-ins, Buckminster may need to be manually told about dependencies outside of the plug-in. A Component Specification (CSPEC) is used for this, and more particularly CSPEC Extensions (CSPEXs) (Both are discussed later below).

There are three basic steps to Buckminsterizing an entire Eclipse project containing plug-ins and features:

  1. Ensure that every component in your project has an implicit or explicit CSPEC. CSPECs/CSPEXs only have to be explicitly written for those components for which Eclipse cannot automatically derive meta-information. For many Eclipse projects, Buckminster can automatically generate complete CPSECs on the fly, and manual intervention is unnecessary.
  2. Write an RMAP so that it and those components on which it depends, can be located. Put this XML file somewhere on your network where others can read it.
  3. Write a CQUERY naming your top level component, and specifying the RMAP (as a URL). Put this XML file somewhere on your network where others can read it.
  4. Tell the others about your CQUERY XML file, and have them open it in Eclipse using File > File Open or equivalent mechanisms as explained above.


Straight-forward cases

If all the components of your Eclipse project are either features or bundles, then nothing at all needs to be done with them: the Buckminster CSPEC generator can do the work for you.

All that remains is the Buckminster RMAP: where can the components be found?

The basic layout of the repositories (CVS, maven or whatever) storing the components needs to be understood, and an RMAP and a CQUERY created for them. You should then execute the CQUERY to verify that everything materialises correctly.

Here for example is the RMAP which the Eclipse STP project team used to Buckminsterise STP (and the CQUERY follows immediately):

<?xml version="1.0" encoding="UTF-8"?>
<rmap
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.eclipse.org/buckminster/RMap-1.0"
    xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0"

    <searchPath name="soas.features">
       <provider readerType="cvs" componentTypes="osgi.bundle,eclipse.feature,buckminster" mutable="true" source="true">
          <uri format=":pserver:anonymous@dev.eclipse.org:/cvsroot/stp,org.eclipse.stp.soas/features/{0}">
              <bc:propertyRef key="buckminster.component" />
          </uri>
       </provider>
    </searchPath>
 
    <searchPath name="soas.plugins">
       <provider readerType="cvs" componentTypes="osgi.bundle,eclipse.feature,buckminster" mutable="true" source="true">
          <uri format=":pserver:anonymous@dev.eclipse.org:/cvsroot/stp,org.eclipse.stp.soas/{0}">
              <bc:propertyRef key="buckminster.component" />
          </uri>
       </provider>
    </searchPath>

    <searchPath name="stp.sc">
       <provider readerType="cvs" componentTypes="osgi.bundle,eclipse.feature,buckminster" mutable="true" source="true">
          <uri format=":pserver:anonymous@dev.eclipse.org:/cvsroot/stp,org.eclipse.stp.servicecreation/{0}">
              <bc:propertyRef key="buckminster.component" />
          </uri>
       </provider>
     </searchPath>

     <searchPath name="datatools.connectivity">
        <provider readerType="cvs" componentTypes="osgi.bundle,eclipse.feature,buckminster" mutable="true" source="true">
            <uri format=":pserver:anonymous@dev.eclipse.org:/cvsroot/datatools,org.eclipse.datatools.connectivity/R1.0/{0}">
                <bc:propertyRef key="buckminster.component" />
           </uri>
        </provider>
     </searchPath>

     <searchPath name="b2j.plugins">
	<provider readerType="cvs" componentTypes="osgi.bundle,eclipse.feature,buckminster" mutable="true" source="true">
	     <uri format=":pserver:anonymous@dev.eclipse.org:/cvsroot/stp,org.eclipse.stp.b2j/{0}">
		<bc:propertyRef key="buckminster.component" />
	     </uri>
        </provider>
     </searchPath>
<!--
     <searchPath name="imported">
        <provider readerType="eclipse.import" componentTypes="osgi.bundle,eclipse.feature" mutable="true" source="true">
             <uri format="file:/c:/M7/site/eclipse?importType=binary"/>
        </provider>
     </searchPath>
-->
     <locator searchPathRef="soas.features" pattern="^org\.eclipse\.stp\.soas\.(.*\.)?feature" />
     <locator searchPathRef="soas.plugins" pattern="^org\.eclipse\.stp\.soas(\..*)?" />
     <locator searchPathRef="stp.sc" pattern="^org\.eclipse\.stp\.sc(\..*)?" />
     <locator searchPathRef="stp.sc" pattern="^org\.eclipse\.stp\.common(\..*)?" />
     <locator searchPathRef="b2j.plugins" pattern="^org\.eclipse\.stp\.b2j(\..*)?" />
     <locator searchPathRef="datatools.connectivity" pattern="^org\.eclipse\.datatools\.connectivity(\..*)?" />

<!--
    <locator searchPathRef="imported" pattern="^org\.eclipse\.emf(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.eclipse\.wst(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.eclipse\.jst(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.eclipse\.jem(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.eclipse\.xsd(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.eclipse\.perfmsr(\..*)?" />
    <locator searchPathRef="imported" pattern="^org\.apache(\..*)?" />
-->
</rmap>

As you can see, there are multiple CVS repositories for soas.features, soas.plugins, stp.sc, datatools.connectivity and b2j.plugins. There are two locators for the stp.sc repository, corresponding to two sets of components org.eclipse.stp.sc and org.eclipse.stp.common. Also you will see commented out XML for the same component sets which was used to help develop and debug the RMAP, when Buckminster was instructed to seek pre-built binaries obtained from the Eclipse Update Sites, rather than using source for components which essentially were external to STP.

The RMAP above was put into a local file stp.rmap, and then given to the corresponding simple CQUERY:

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="file:/C:/workspaces/STPTest/build.test/stp.rmap">
    <cq:rootRequest name="org.eclipse.stp.soas.feature" componentType="eclipse.feature"/>
</cq:componentQuery>

Once the materialisation completed, the component org.eclipse.stp.soas.feature materialises into the current workspace. Right-clicking on the package explorer view for the component throws up the usual Buckminster > Invoke Action.. option. Selecting the feature.exports action (which was automatically generated by Buckminster as part of the associated CSPEC) then proceeds to build the feature and all of its various plug-ins -- a properties file such as

buckminster.output.root=c:/temp/stp.build.output

can be given to the Invoke Action.. window so as to control to which directory the built output goes.





Put together a virtual distribution

A virtual distribution ("distro") is software distribution made available via a hosting server (e.g. somewhere on the internet): however the hosting server itself does not store any of the binaries or other (eg source) components that make up the distribution - in that sense, it is virtual. The virtual distro is actually a set of pointers to places where the component binaries and/or source codes can be obtained during the materialization.

Sometimes "virtual distro" however is taken as having a different meaning: a package of operating system software hosted above a native operating system. Such "virtual hosting" is quite different from the "virtual distribution" capabilities enabled by Buckminster.

A virtual distro is in practice a set of metadata stored in a hosting server. The metadata contains information about the components forming the distro. Each of the components may define dependencies on other components. If the virtual distro be materializable (ie downloadable), then all component dependencies must be resolved prior to materialization.

Frequently it is possible to create a set of virtual distros, using essentially the same set of components configured in different ways, tailoring to particular use cases.

The role of the publisher of the virtual distro is to define complete set of components to be materialized. The process of virtual distro materialization is as follows:

  • reading virtual distro metadata
  • resolution of all component dependencies
  • downloading components from their locations
  • performing post-download actions on the downloaded components




Creating and Publishing a Virtual Distro: an example

A virtual distro is defined by the topmost component. The top component itself is not necessarily itself mapped to any binaries or source code: it can instead just define some distro attributes (name, version, description etc.) and dependencies on other components.

The top component is described with the Buckminster CSPEC file. Once the CSPEC is created, it can be made available to the community of users (e.g. using a site like Cloudsmith). CSPECs can be automatically generated by Buckminster for Eclipse plugins and features. However, for this example, we will write CSPECs manually.

The top component can depend on two different types of components:

  • virtual components
  • materializable components

A virtual component is just yet another component which in turn simply refers to another set of components (with attributes and dependencies). It may optionally define post-download actions on the materialized components. It does not usually point to any binaries or source code.

A materializable component points to the binaries or source code (or both), stored at appropriate repositories somewhere in the internet. In additon, it may define attributes, dependencies on other components, etc.

To better understand this all, we'll use the example of the virtual distro for the Lomboz for Web Minimal for Windows, version 3.2.2. We will show you the steps necesssary to be a publisher of a virtual distro, using Buckminster, for some audience community of users who may wish to us the virtual distro.

In fact several similar distros can be created using essentially the same structure of reusable virtual components. We initially define the top component, which in turn defines dependencies on two other components – the windows specific one, and the collection of platform independent components for this distro.

The top component is called, for the example, com.eteration.lomboz4web-win32-minimal. The CSPEC written for it is:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec
   xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0"
   name="com.eteration.lomboz4web-win32-minimal"
   shortDesc="Lomboz for Web Minimal (Win32)"
   version="3.2.2"
   versionType="OSGi">

   <cs:dependencies>
	<cs:dependency name="org.objectweb.lomboz.product.lomboz-all-in-one-win32"/>
	<cs:dependency name="com.eteration.lomboz4web-platform-independent-minimal"/>
   </cs:dependencies>
</cs:cspec>

As you can see, this manually written CSPEC is reasonably straight-forward:

  • The first three lines relate to standard XML declaratons.
  • The name of the component described by the CSPEC then follows, in this case com.eteration.lomboz4web-win32-minimal.
  • There is then a short textual description, and some version information. Versioning is described in more detail in Why Buckminster? introduction and there is a fuller description in the Buckminster meta-data language guide.
  • There then follow two dependencies: the current component in turn depends on the components org.objectweb.lomboz.product.lomboz-all-in-one-win32 and com.eteration.lomboz4web-platform-independent-minimal

More detailed examples of CSPECs below if you are interested.

The component org.objectweb.lomboz.product.lomboz-all-in-one-win32 in fact is materializable (ie it consists of binary and/or source).

The com.eteration.lomboz4web-platform-independent-minimal component is a virtual component. We have to write another component specification, again as a CSPEC:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0"
   name="com.eteration.lomboz4web-platform-independent-minimal"
   shortDesc="Lomboz for Web Minimal (Platform Independent)"
   version="3.2.2"
   versionType="OSGi">

   <cs:dependencies>
       <cs:dependency name="com.eteration.lomboz-common"/>
       <cs:dependency name="apache-tomcat"/>
   </cs:dependencies>
</cs:cspec>

The apache-tomcat component is a materializable.

The com.eteration.lomboz-common component is another virtual component, and here is the CSPEC written for it:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0"
   name="com.eteration.lomboz-common"
   shortDesc="Lomboz for Web/Enterprise/Portals Minimal (common)"
   version="3.2.2"
   versionType="OSGi">

   <cs:dependencies>
	<cs:dependency name="struts"/>
	<cs:dependency name="myfaces-core"/>
	<cs:dependency name="spring-framework"/>
	<cs:dependency name="hibernate-core"/>
   </cs:dependencies>
</cs:cspec>

All the components upon which this component depends are materializable.

At this point, we have defined a tree of related components, all of whose leaves are materializable. We have written a set of CSPECs, one for each virtual component - and if any of the components had been Eclipse plugins or features, they would not need to have been manually written - and these CSPECs will need to be made available to our audience. Cloudsmith is of course one concise and natural way to publish such virtual distros (including necessary CSPECs) to an audience.


The CQUERY

The CQUERY for the top level component (com.eteration.lomboz4web-win32-minimal) is:

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap={RMAP URL to be filled in}>
	<cq:rootRequest name="com.eteration.lomboz4web-win32-minimal"/>
</cq:componentQuery>

Note that an RMAP must be provided: a sample RMAP is given later below.

Because no specific version is given in the CQUERY, Buckminster will look for the latest version available. More sophisticated queries - such as version over-riding and/or exclusion of specific components - are of course possible, and the The CQUERY also allows to specify exceptions, like version overriding, component exclusion etc. For more details, see the Buckminster meta-data language guide documentation.

The CQUERY - like the CSPECs we wrote above - will have to be published to our audience community, so that they can use our virtual distro: once again Cloudsmith is one tool which can make this easy.

Resolving this query (using the usual approach, see Materializing an existing component) will yield a bill of materials. The bill of materials is a set of pointers to all the specific components needed for materialization of the distro, together with their respective locations.

Users - those we wish to be able to materialise the top level component com.eteration.lomboz4web-win32-minimal - can be given the original CQUERY, or the bill of materials. However, we can make things even more convenient, and avoid users having to select the destination for each component (or at least specifying a default destination). A Buckminster MSPEC can be used instead, which allows us (ie the publisher of the virtual distro) to predefine destination locations: this is discussed later below.

First however, we should consider the RMAP for the CQUERY.



The RMAP

A possible RMAP for the virtual distro is:

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0"
  xmlns:mp="http://www.eclipse.org/buckminster/MavenProvider-1.0"
  xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0">

  <rm:searchPath name="lomboz-win32">
    <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	<rm:uri format="http://download.fr2.forge.objectweb.org/lomboz/org.objectweb.lomboz-all-in-one-R-3.2.2-200706042126-win32.zip"/>
    </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="spring">
    <rm:provider
	readerType="site.feature"
	componentTypes="site.feature"
	mutable="false" source="false">
	<rm:uri format="http://springide.org/updatesite"/>
    </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="hibernate-tools">
    <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	<rm:uri format="http://switch.dl.sourceforge.net/sourceforge/jboss/HibernateTools-nodeps-3.2.0.beta9a.zip"/>
    </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="apache-tomcat">
     <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	<rm:uri format="http://www.apache.org/dist/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip"/>
     </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="myfaces-core">
     <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	<rm:uri format="http://mirror.styx.cz/apache/myfaces/binaries/myfaces-core-1.1.5-bin.zip"/>
     </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="spring-framework">
     <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	<rm:uri format="http://switch.dl.sourceforge.net/sourceforge/springframework/spring-framework-2.0.5.zip"/>
     </rm:provider>
  </rm:searchPath>

  <rm:searchPath name="hibernate-core">
      <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	 <rm:uri format="http://switch.dl.sourceforge.net/sourceforge/hibernate/hibernate-3.2.4.ga.zip"/>
      </rm:provider>
   </rm:searchPath>

   <rm:searchPath name="xdoclet">
      <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	 <rm:uri format="http://switch.dl.sourceforge.net/xdoclet/xdoclet-bin-1.2.3.zip"/>
      </rm:provider>
   </rm:searchPath>

   <rm:searchPath name="struts">
      <rm:provider readerType="url" componentType="unknown" mutable="true" source="false">
	  <rm:uri format="http://www.apache.org/dist/struts/binaries/struts-1.3.8-all.zip"/>
      </rm:provider>
   </rm:searchPath>

   <rm:locator searchPathRef="lomboz-win32" pattern="\Qorg.objectweb.lomboz.product.lomboz-all-in-one-win32\E" />
   <rm:locator searchPathRef="spring" pattern="\Qorg.springframework.ide.eclipse\E.*" />
   <rm:locator searchPathRef="hibernate-tools" pattern="\Qhibernate-tools\E" />
   <rm:locator searchPathRef="apache-tomcat" pattern="\Qapache-tomcat\E" />
   <rm:locator searchPathRef="myfaces-core" pattern="\Qmyfaces-core\E" />
   <rm:locator searchPathRef="spring-framework" pattern="\Qspring-framework\E" />
   <rm:locator searchPathRef="hibernate-core" pattern="\Qhibernate-core\E" />
   <rm:locator searchPathRef="xdoclet" pattern="\Qxdoclet\E" />
   <rm:locator searchPathRef="struts" pattern="\Qstruts\E" />
</rm:rmap>


The RMAP - like the CSPECs and CQUERY we wrote above - will also have to be published to our audience community, so that they can use our virtual distro: and also once again Cloudsmith is one tool which can make this easy.



Making use of an MSPEC to further simplify downloading

As noted above, we can make things even more convenient, and avoid users having to select the destination for each component (or at least specifying a default destination) by providing an MSPEC, such as the following:

<?xml version="1.0" encoding="UTF-8"?>
<md:mspec xmlns:md="http://www.eclipse.org/buckminster/MetaData-1.0"
   installLocation="c:/lomboz/install/"
   materializer="filesystem"
   conflictResolution="REPLACE"
   name="Lomboz4Web-Win32-Minimal"
   url= {Insert the URL for the BOM file here }
   shortDesc="Lomboz for Web (Minimal Lomboz distro for Web Development)">

   <md:mspecNode materializer="filesystem" conflictResolution="UPDATE"
       namePattern="com.eteration.lomboz.*" exclude="true"/>
   <md:mspecNode installLocation="eclipse.zips/" materializer="filesystem"
       conflictResolution="UPDATE"
       namePattern="org.objectweb.lomboz.product.lomboz.*"/>
   <md:mspecNode installLocation="frameworks.zips/" materializer="filesystem"
       conflictResolution="UPDATE" namePattern="myfaces-core"/>
   <md:mspecNode installLocation="frameworks.zips/" materializer="filesystem"
       conflictResolution="UPDATE" namePattern="hibernate-core"/>
   <md:mspecNode installLocation="frameworks.zips/" materializer="filesystem"
       conflictResolution="UPDATE" namePattern="spring-framework"/>
   <md:mspecNode installLocation="frameworks.zips/" materializer="filesystem"
       conflictResolution="UPDATE" namePattern="struts"/>
   <md:mspecNode installLocation="servers.zips/" materializer="filesystem"
       conflictResolution="UPDATE" namePattern="apache-tomcat"/>
</md:mspec>

The MSPEC indicates that:

  • The materialisation should be done to the local folder c:/lomboz/install, which is a filesystem, and in general if there are conflicting components already installed on the destination machine, then they should be REPLACEd with the new components being downloaded.
  • All downloaded components whose names match the pattern com.eteration.lomboz.* are virtual, and are excluded.
  • All downloaded components whose names match the pattern org.objectweb.lomboz.product.lomboz.* should go to the folder eclipse.zips/ (under c:/lomboz/install/), but replace any existing components of the same name only if the downloaded ones are more recent version.
  • Likewise myfaces-core, hibernate-core, spring-framework and struts to the folder frameworks.zips/; and apache-tomcat to the folder servers.zips/

Note that the URL to the .bom file, generated (and saved) during query resolution should be inserted in the 6th line above for the url= value.

For more details of MSPECs, see the Buckminster meta-data language guide documentation.

Component Specifications (CSPECs)

If Buckminster cannot derive the necessary component structure from existing meta-data, a CSPEC must be manually created as an XML file. Buckminster provides a wizard to help at File > New > Other > Buckminster > Component Specification file.

Sample CSPECs can be viewed by selecting File > View a selected CSPEC within the Eclipse Java SDK. Some documented examples are also given in this section later below.

A CSPEC lists a set of named attributes: you can think of it as the interface to the component, for Buckminster to use - more specifically, for other components in Buckminster to use. In fact an attribute can either be publicly available (for other CPSECs to use) as part of this interface, or for private use just within the current CSPEC itself.

Each attribute is one of three possibilities:

  • an artifact that denotes one or more pre-existing files and directories (folders). The distinction between a file and a folder/directory depends on whether or not there is a trailing '/' after the name. The <path> sub-element can be used when more then one file or directory is desired; OR
  • an action that describes something that can be carried out in order to produce zero or more new artifacts (ie files or directories); OR
  • a group, which is an arbitrary grouping of artifact, action, and group instances. It can be trivially used just to provide further alternate names for atrributes and/or make private attributes public (the analogy is a method which can return the value of another method). However a group is more usefully adopted to bring together the output of several attributes into one single attribute.

To implement action attributes, currently Buckminster only supports ant as an actor scripting language. Parameters may be passed to the actor via actorProperties values (for example targets in the case of ant to describe the targets which ant should try to build). There are also certain "built-in" actions: eclipse.clean to request a clean build from the Eclipse build system; eclipse.build to request a full build from the Eclipse build system; and buckminster.prebind, which is called by the "workspace" materializer after it has completed a download, but before the component is bound to the Eclipse workspace. This action is not expected to have a product. Its primary purpose is to rearrange things or copy things into a project.

Finally, a CSPEC may also define a list of dependencies to other components. Such dependencies are referred from actions, prerequisites and groups.


Here is a simple example of an artifact and a group (but not a complete CSPEC):

<cs:artifacts>
  <cs:public name="foo.jar" path="com.ics.jar" type="bundle.jar" base="../"/>
</cs:artifacts>
<cs:groups>
  <cs:public name="java.binaries">
      <cs:attribute name="foo.jar"/>
  </cs:public>
</cs:groups>

Here an artifact foo.jar denotes a single file located at ../com.ics.jar, which is of type bundle.jar. If the base is omitted, the name of the component (described by the CSPEC) is assumed. The type field is essentially at this time only documentation, and serves no other purpose. Because of the groups declaration, the foo.jar artifact ends up in practice having two externally visible names: foo.jar and java.binaries. The java.binaries is something that is intended to participate in a classpath that can be used by actions that are dependent on this component. The foo.jar is intended to be a packed bundle, suitable for an update site.


Consider another simple example (again, not a complete CSPEC):

<cs:artifacts>
  <cs:private name="bundle.classpath" type="java.binaries">
    <cs:path path="resolver.jar"/>
    <cs:path path="xercesImpl.jar"/>
    <cs:path path="xml-apis.jar"/>
  </cs:private>
</cs:artifacts>
<cs:groups>
  <cs:public name="java.binaries">
    <cs:attribute name="bundle.classpath"/>
  </cs:public>
</cs:groups>

Here, bundle.classpath and java.binaries are alternative names for the collection of files resolver.jar, xercesImpl.jar, and xml-apis.jar. However only java.binaries is visible as an attribute outside the CSPEC: the attribute bundle.classpath is presumably used privately elsewhere within the (rest of the) CSPEC.


A full example of a CSPEC

Here is an example of a full CSPEC for a component called org.demo.worlds:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0" name="org.demo.worlds">
    <cs:artifacts>
    	<cs:public name="source" path="src/"/>
    </cs:artifacts>
    <cs:actions>
        <cs:public name="java.binary.archives" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFile" value="make/build.xml"/>
            </cs:actorProperties>
            <cs:prerequisites alias="input">
                <cs:local attribute="eclipse.build"/>
            </cs:prerequisites>
            <cs:products alias="output" base="bin/jars/">
                <cs:path path="worlds.jar"/>
            </cs:products>
        </cs:public>
        <cs:private name="eclipse.build">
            <cs:prerequisites>
                <cs:local attribute="source"/>
            </cs:prerequisites>
            <cs:products base="bin/classes/">
                <cs:path path="."/>
            </cs:products>
        </cs:private>
    </cs:actions>
    <cs:groups>
    	<cs:public name="java.binaries">
    		<cs:local attribute="eclipse.build"/>
    	</cs:public>
    </cs:groups>
</cs:cspec>

This meta-data describes the following:

  • The first two lines declare that this is XML; it follows the CSPEC format, and it describes a component called org.demo.worlds
  • The next section lists the component attributes that are considered artifacts in this CSPEC. In this case there is only one declaration, a public attribute (available both within this CSPEC and to other CSPECs) called source, that is mapped to a folder called org.demo/worlds/src/
  • The next section lists the component attributes that are implemented as actions:
  1. The first action is java.binary.archives, and is publicly available to other CSPECs from this CSPEC.
    1. It is implemented using an ant actor: when ant is invoked by Buckminster as part of this particular action, it is passed make/build.xml as the value of the standard buildFile parameter to ant.
    2. The action has one prerequisite - the local (local to this CSPEC) action eclipse.build (see the next action in this CSPEC) which must be completed before this action can execute. This prerequisite also has an alias name input which can (only) be used within ant to refer to the same attribute eclipse.build.
    3. The result of the action is a product in the file base bin/jars/worlds.jar; ant can also reference this as output.
  2. The second action is eclipse.build, and is private (local) to this particular CSPEC. Accessing this (action) attribute does not invoke an ant action but instead causes the Eclipse build system to run:
    1. It has one prerequisite - the local (local to this CSPEC) attribute source/ must exist: from above, this tests that the folder src/ exists.
    2. The result of the action is a directory called bin/classes/.
  • Finally, there is a publicly available (group) attribute called java.binaries, which in fact is implemented by the single local action called eclipse.build described above: the value of java.binaries is whatever eclipse.build generates.

In summary: this CSPEC, for a component called org.demo.worlds has three externally visible attributes:

  • source, which in fact is the contents of the folder org.demo.worlds/src/;
  • java.binary.archives, which in fact is the file org.demo.worlds/bin/jars/world.jar/ but only available once generated by an ant actor, and in turn only once the Eclipse build system has been called as a local action on this component;
  • java.binary, which in fact is the directory org.demo.worlds/bin/classes/., but only available once the Eclipse build system has been called as a local action on this component.


A complex example of a CSPEC

Here is an example of a Buckminster generated CSPEC for a component called org.eclipse.buckminster.core.feature:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0" name="org.eclipse.buckminster.core.feature" componentType="eclipse.feature" 
version="0.1.0.v20070618" versionType="OSGi">
    <cs:dependencies>
        <cs:dependency name="org.eclipse.buckminster.ant" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.cmdline" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.core" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.installer" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.runtime" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.sax" componentType="osgi.bundle"/>
        <cs:dependency name="org.eclipse.buckminster.ui" componentType="osgi.bundle"/>
    </cs:dependencies>
    <cs:artifacts>
        <cs:private name="build.properties" base="build.properties/"/>
        <cs:private name="jar.contents">
            <cs:path path="feature.properties"/>
            <cs:path path="epl-v10.html"/>
            <cs:path path="license.html"/>
            <cs:path path="COPYRIGHT"/>
        </cs:private>
        <cs:private name="raw.manifest" path="feature.xml"/>
    </cs:artifacts>
    <cs:actions>
        <cs:public name="buckminster.clean" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFileId" value="buckminster.pdetasks"/>
                <cs:property key="targets" value="delete.dir"/>
            </cs:actorProperties>
            <cs:properties>
                <cs:property key="dir.to.delete" value="${buckminster.output}/"/>
            </cs:properties>
            <cs:prerequisites>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.ui"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.cmdline"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.installer"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.runtime"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.ant"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.core"/>
                <cs:attribute name="buckminster.clean" component="org.eclipse.buckminster.sax"/>
            </cs:prerequisites>
        </cs:public>
        <cs:public name="manifest" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFileId" value="buckminster.pdetasks"/>
                <cs:property key="targets" value="expand.feature.version"/>
            </cs:actorProperties>
            <cs:prerequisites>
                <cs:attribute name="raw.manifest" alias="manifest"/>
                <cs:attribute name="bundle.jars" alias="bundles"/>
                <cs:attribute name="feature.references" alias="features"/>
                <cs:attribute name="build.properties" alias="properties"/>
            </cs:prerequisites>
            <cs:products alias="action.output" base="${buckminster.output}/temp/">
                <cs:path path="feature.xml"/>
            </cs:products>
        </cs:public>
        <cs:private name="copy.features" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFileId" value="buckminster.pdetasks"/>
                <cs:property key="targets" value="copy.group"/>
            </cs:actorProperties>
            <cs:prerequisites alias="action.requirements">
                <cs:attribute name="feature.jars"/>
            </cs:prerequisites>
            <cs:products alias="action.output" base="${buckminster.output}/site/features/" upToDatePolicy="MAPPER"/>
        </cs:private>
        <cs:private name="copy.plugins" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFileId" value="buckminster.pdetasks"/>
                <cs:property key="targets" value="copy.group"/>
            </cs:actorProperties>
            <cs:prerequisites alias="action.requirements">
                <cs:attribute name="bundle.jars"/>
            </cs:prerequisites>
            <cs:products alias="action.output" base="${buckminster.output}/site/plugins/" upToDatePolicy="MAPPER"/>
        </cs:private>
        <cs:private name="feature.jar" actor="ant">
            <cs:actorProperties>
                <cs:property key="buildFileId" value="buckminster.pdetasks"/>
                <cs:property key="targets" value="create.feature.jar"/>
            </cs:actorProperties>
            <cs:prerequisites alias="action.requirements">
                <cs:attribute name="manifest" alias="manifest"/>
                <cs:attribute name="jar.contents"/>
            </cs:prerequisites>
            <cs:products alias="action.output" base="${buckminster.output}/jar/" fileCount="1" upToDatePolicy="COUNT"/>
        </cs:private>
    </cs:actions>
    <cs:groups>
        <cs:public name="bundle.jars">
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.ui"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.cmdline"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.installer"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.runtime"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.ant"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.core"/>
            <cs:attribute name="bundle.jar" component="org.eclipse.buckminster.sax"/>
        </cs:public>
        <cs:public name="feature.exports" rebase="${buckminster.output}/site/">
            <cs:attribute name="copy.features"/>
            <cs:attribute name="copy.plugins"/>
        </cs:public>
        <cs:public name="feature.jars">
            <cs:attribute name="feature.jar"/>
            <cs:attribute name="feature.references"/>
        </cs:public>
        <cs:public name="feature.references"/>
        <cs:public name="product.root.files"/>
    </cs:groups>
</cs:cspec>

OK. Take a deep breath and get a coffee (I did, while I wrote this). The result of all this is a CSPEC with the following attributes (all file and directory names are relevant to the component name org.eclipse.buckminster.core.feature:

  • A private attribute build.properties located in the directory build.properties/
  • A private attribute jar.contents which is the collection of files feature.properties, epl-v10.html, license.html and COPYRIGHT
  • A private attribute raw.manifest which is the file feature.xml
  • A public attribute buckminster.clean which is implemented as an ant actor, setting its buildFileId as buckminster.pdetasks and targets as delete.dir; in addition ${buckminster.output} is passed as the defined value (-Dprop=value) of dir.to.delete to ant. There are however a number of prerequisites for this action: the attribute buckminster.clean is accessed on each of the other components org.eclipse.buckminster.ui, org.eclipse.buckminster.cmdline, org.eclipse.buckminster.installer, org.eclipse.buckminster.runtime, org.eclipse.buckminster.ant, org.eclipse.buckminster.core and org.eclipse.buckminster.sax. Note that there is no result or output from this action: there is no products field.
  • A public attribute manifest, also implemented as an ant actor, setting its buildFileId as buckminster.pdetasks and its targets as expand.feature.version. The action has prerequisites - all of which are other attributes appearing elsewhere in the CSPEC (ie in the big list you are currently reading): raw.manifest, also available as the name manifest to ant; bundle.jars, and as bundles to ant; feature.references, and as features to ant; and build.properties, as properties to ant. It yields a result ${buckminster.output}/temp/feature.xml, also known as action.output within ant.
  • A private attribute copy.features, implemented in ant, setting its buildFileId as buckminster.pdetasks and targets as copy.group. It has one prerequisite attribute (appearing elsewhere in the CSPEC) called feature.jars, known as action.requirements to ant. Its value is the contents of ${buckminster.output}/site/features/, also known as action.output to ant. However, the action has an uptoDatePolicy setting, an optimisation hint which may reduce the work Buckminster needs to do. The MAPPER setting compares the product with each corresponding prerequsite: if there is match and the product is younger than the prerequisite then the action can be skipped, since the results of the action were previously done and are already in place.
  • A private attribute copy.plugins, similar in style to the copy.features attribute above.
  • A private attribute feature.jar, somewhat similar in style to both the copy.features and copy.plugins above. However the uptToDatePolicy optimistion hint is set to COUNT and with fileCount=1, meaning that the action can be skipped as unnecessary if at least one file in the products ${buckminster.output}/jar/ is younger than the youngest artifact found in the prerequisites mainfest and jar.contents
  • A public attribute bundle.jars which is the collection of all the <bundle.jar> attributes of each of each of the other components org.eclipse.buckminster.ui, org.eclipse.buckminster.cmdline, org.eclipse.buckminster.installer, org.eclipse.buckminster.runtime, org.eclipse.buckminster.ant, org.eclipse.buckminster.core and org.eclipse.buckminster.sax.
  • A public attribute feature.exports, which is both of the (private) attibutes copy.features and copy.plugins as above, but with the directory ${buckminster.output}/site/ overriding the base directory settings in those two attributes.
  • A public attribute feature.jars, which is the pair of attributes feature.jar and feature.references.
  • Two public attributes feature.references and product.root.files, which in fact are both dummy attributes having no value, and placeholders -- this is a generated CSPEC.

My coffee is cold, time for another.



Extended Component Specifications (CSPEXs)

In some cases, not all information that needs to be described can be declared in ordinary plug-in meta-data. In these cases, Buckminster makes it possible to extend the automatically generated CSPEC by manually providing a CSPEC Extension ("CSPEX") file buckminster.cspex, which must be placed into the same directory/folder as the component itself, and which follows the general CSPEC format.

In general, a CSPEX enables you to manually extend, and add to, automatically generated CSPEC files with further metadata that is not readily deducible by Buckminster.

Here is an example, from the Hello World example, and reproduced below for convenience:

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspecExtension
  xmlns:com="http://www.eclipse.org/buckminster/Common-1.0"
  xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0">
  <cs:dependencies>
    <cs:dependency name="org.demo.worlds"/>
    <cs:dependency name="se.tada.util.sax"  versionDesignator="1.0.0" versionType="OSGi"/>
  </cs:dependencies>

  <cs:actions>
    <cs:public name="buckminster.prebind" actor="ant">
      <cs:actorProperties>
	<cs:property key="buildFile" value="make/prebind.xml" />
      </cs:actorProperties>
      <cs:prerequisites>
         <cs:attribute component="se.tada.util.sax" alias="tada-sax.jar" name="java.binary.archives"/>
	 <cs:attribute component="org.demo.worlds" alias="worlds.jar" name="java.binary.archives"/>
      </cs:prerequisites>
      <cs:products alias="output">
         <cs:path path="jars/" />
      </cs:products>
    </cs:public>
  </cs:actions>
</cs:cspecExtension>

This extension works as follows:

  • Lines 1-4 are the XML content and declarations of namespaces. Note the use of a cspecExtension element as the top most element.
  • Next, two dependencies are listed for the current component, on both components org.demo.worlds and se.tada.util.sax. Buckminster needs to find both before the current component can be processed.
  • The actions section declares a private (local to this CSPEX) action buckminster.prebind as an ant action. As for CSPECs, the name buckminster.prebind has specific implication for Buckminster, and results in an action initiated once a component is downloaded but before it is bound into the current workspace. The ant actor is passed make/prebind.xml as the value of its buildFile parameter.
  • There are two pre-requisites to the action.
  1. The first is on attribute java.binary.archives in the component se.tada.util.sax, and is known within the ant script as tada-sax.jar.
  2. The second is on the attribute java.binary.archives in the component org.demo.worlds, and is also known within the ant script as worlds.jar.
  • The products section declares that the result is known as output to the ant script, and is produced in the folder jars/.