Skip to main content
Jump to: navigation, search

Difference between revisions of "Introduction to Buckminster"

 
(Getting Started)
 
(107 intermediate revisions by 10 users not shown)
Line 1: Line 1:
=Welcome to Buckminster=
+
{{Backlink|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.
  
<p>If you've already read this introduction, you can skip straight to the [[Buckminster_Project/docs/drafts/Reference|reference material]].</p>
+
If you are new to Buckminster, then you should read the [http://wiki.eclipse.org/Why_Buckminster_%3F Why Buckminster?] document first.
  
==In Its Simplest Form==
+
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. 
  
<p>In its simplest form, Buckminster solves the following problem:</p>
+
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 [[Getting started with Buckminster#Installation | 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|Materialize an existing component (and those on which it depends)]]
 +
* [[#Publish an existing component|Publish an existing component (and those on which it depends) so that others can materialize your component]]
 +
* [[#Publish your Eclipse project|Publish your Eclipse project:  “Buckminsterizing” your project and sharing it with your team]]
 +
* [[#Put together a virtual distribution|Put together a virtual distribution for a set of various packaged components]]: you want to publish your product and share with the whole software community.
 +
 +
 +
 +
 +
 +
 +
 +
 +
=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 [[#Materializing using a pre-existing Bill Of Materials|section]].
 +
 +
 +
A sample CQUERY is online [http://www.eclipse.org/buckminster/samples/queries/demo.cquery here],  from the [http://wiki.eclipse.org/index.php/Hello_XML_World_Example_%28Buckminster%29 Hello World] example, and reproduced below for convenience:
 +
<pre>
 +
<?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>
 +
</pre>
 +
The first line indicates that the file contains XML. 
 +
 +
The second line gives a CQUERY (from the XML name space <tt>http://www.eclipse.org/buckminster/CQuery-1.0</tt>) and also identifies a Resource Map (or RMAP).  RMAPs are discussed later [[#Resource Maps (RMAPs)|below]].    The <tt>resourceMap</tt> entry may in fact be omitted,  in which case Buckminster will attempt to resolve the CQUERY locally or by using preconfigured remote resolvers.
 +
 +
The <tt>rootRequest</tt> identifies the name of the top most component required – here <tt>org.demo.hello.xml.world</tt>.  The (optional) componentType identifies this component as a <tt>osgi.bundle</tt> (an Eclipse plugin).
 +
Finally the <tt>versionType</tt> 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 <tt>[0-9].[0-9].[0-9].[a-zA-Z0-9_-]</tt> (for example: <tt>3.2.0.RC_beta-1</tt>).  Alternative values for the <tt>versionType</tt> are <tt>String;  Timestamp;</tt>  or <tt>Triplet</tt>.  An overview of versioning is given [http://wiki.eclipse.org/Why_Buckminster_%3F#Versioning Why Buckminster? introduction] and there is a fuller description in the [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29 Buckminster meta-data language guide].
 +
 +
 +
You can find the CQUERY wizard to help you write CQUERY XML files in <tt>File > New > Other > Buckminster > Component Query File</tt>. Enter an appropriate <tt>Container</tt> and <tt>File name</tt> in which you want your new CQUERY to be placed.  Then fill in the fields of the form as needed:
 
<ul>
 
<ul>
  <li>Your colleague say &quot;ok, project Overland is ready for you to work on
+
<li>the <tt>Component Name</tt> is the top level name of your target component,  and will be the <tt>rootRequest</tt> for the CQUERY</li>
    - just check out <samp>com.megacorp.overland</samp> from CVS and get
+
<li><tt>Properties</tt> and <tt>Advisor Nodes</tt> (see the tabbed form at the bottom of the pane) are advanced topics,  discussed '''TBD'''</li>
    started.</li>
+
<li>An RMAP should normally be given.  We discuss this in a later section [[#Resource Maps (RMAPs)|below]].</li>
  <li>You checkout com.megacorp.overland and discover that it has unresolved
+
    project dependencies.</li>
+
  <li>&quot;Oh yeah,&quot; he says, &quot;you have to checkout project overwater
+
    as well&quot;. Of course that doesn't completely solve the problem...</li>
+
  <li>&quot;Also you have to get the latest undersea.jar from the central FTP
+
    server.&quot;</li>
+
  <li>Eventually, after a few rounds of this, you have the whole set of
+
    resources and you are ready to go to work.</li>
+
 
</ul>
 
</ul>
 +
At the bottom of the wizard,  there are three buttons:  select <tt>External Save As</tt> to save your CQUERY as an external file.
 +
 +
 +
To actually execute a CQUERY:
 +
<ul>
 +
<li>either select <tt>File > Open File</tt> within in the Eclipse Java SDK,  and enter the URL for the CQUERY in the <tt>File Name</tt> field.  This will then start the CQUERY wizard and populate it with the data from the CQUERY file you specified ''OR''</li>
 +
<li>use the CQUERY wizard directly ''OR''</li>
 +
<li>use <tt>File > Import > Other > Materialize from Buckminster MSPEC, CQUERY or BOM</tt>,  pressing <tt>Next</tt> and then the URL for the CQUERY and the <tt>Load</tt> button.</li>
 +
</ul>
 +
In each case, proceed to select the <tt>Resolve to Wizard</tt> or,  more directly, <tt>Resolve and Materialise</tt> button.  <tt>Resolve to Wizard</tt> 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 <tt>Next</tt> and the platform environment settings can be examined,  and the generated MSPEC saved if you so wish.  Press <tt>Finish</tt> to execute the materialisation.
 +
 +
When materialization starts, a new window will open, entitled <tt>Resolving Query</tt>, 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:
 +
#Write a CQUERY in XML into a file, either directly using an editor or by using the CQUERY wizard.
 +
#State the name of the top level component you are materializing.
 +
#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.
 +
#Enter the file name of your CQUERY file into <tt>File > Open File</tt> 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 [http://wiki.eclipse.org/Why_Buckminster_%3F 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 <tt>Resolve to Wizard</tt>.
 +
 +
Subsequently,  the BOM file can be used by selecting <tt>File > Import > Other > Materialize from Buckminster MSPEC, CQUERY or BOM</tt>; pressing <tt>Next</tt>; then the URL for the BOM file,  and finally the <tt>Load</tt> button.  Note that if instead you simply pass a BOM file to <tt>File > New File</tt>,  the BOM file will be displayed as a text file.
 +
 +
After the BOM file is loaded,  press either <tt>Finish</tt> to complete the materialization,  or <tt>Next</tt> to allow finer control as in the CQUERY <tt>Resolve to Wizard</tt> (explained in the previous [[#Materialize an existing component|section]]),  followed eventually by <tt>Finish</tt> 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: <tt>Window > Show view > Package Explorer</tt>.
 +
 +
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 <tt>Buckminster > Invoke Action..</tt> and <tt>Buckminster > View CSPEC..</tt>
 +
 +
<tt>Invoke Action..</tt> allows you to click on any of the publicly available <tt>action</tt> attributes defined for this particular component.  <tt>Action</tt> attributes are discussed in detail [[#Component Specifications (CSPECs)|below]].  An optional <tt>Properties</tt> file can be also be specified as context for whatever action you select:  for example,  to specify the output folder for a build action.
 +
 +
<tt>View CPSEC..</tt> 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 <tt>action</tt> attributes which <tt>Invoke Action..</tt> can use,  together with other attributes.  CSPECs are discussed in detail [[#Component Specifications (CSPECs)|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 [[#Materialize an existing component|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 <tt>locator</tt> 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 <tt>searchPath</tt>,  as we will see below.
 +
 +
Third, the RMAP allows variability by setting alternative values for the <tt>locator</tt>s. 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 <tt>locator</tt> 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 <tt>locator</tt>s in order,  the last <tt>locator</tt> 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 <tt>File > New > Other > Buckminster > Resource Map File</tt>.
 +
 +
Here is a simple RMAP (and is online [http://www.eclipse.org/buckminster/samples/rmaps/demo.rmap here]), from the [http://wiki.eclipse.org/index.php/Hello_XML_World_Example_%28Buckminster%29 Hello World] example,:
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
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 <tt>searchPaths</tt>: the first is called <tt>default</tt>, and the second is called <tt>maven</tt>.
 +
 
 +
Continue down and you find two <tt>locator</tt> declarations.  These map patterns of component names,  to specific <tt>searchPaths</tt>:
 +
* the first states that if a component name starts with the pattern <tt>se.tada.</tt> then the <tt>maven</tt> search path should be used; and
 +
* the second locator states that if a component name starts with the pattern <tt>org.demo.</tt> then the <tt>default</tt> path should be used.
 +
Note that <tt>locator</tt> entries are tried in order:  in this example,  Buckminster will first try to match component names beginning with <tt>se.tada.</tt> (and if matched,  then hence the <tt>maven</tt> repository),  before the second entry.  Thus in general,  the <tt>locator</tt> 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 <tt>searchPathRef</tt> value may occur in multiple <tt>locator</tt> declarations.  For example,  we could add a further declaration:
 +
<pre>
 +
    <rm:locator searchPathRef="default" pattern="^hi\.hello\..*" />
 +
</pre>
 +
and thus components whose name started with <tt>se.tada</tt> or with <tt>hi.hello</tt> would in each case map to the <tt>maven</tt> search path.
 +
 +
Back to the <tt>searchPath</tt>s themselves.  An RMAP can have one or more <tt>searchPath</tt>s,  and the order in which they appear is ''not'' significant.  Each <tt>searchPath</tt> must have one or more <tt>provider</tt>s,  and if more than one <tt>provider</tt> is given,  they will be tried in order for that particular <tt>searchPath</tt>.  In our case,  we have two paths:
 +
#The <tt>default</tt> path:
 +
##The <tt>default</tt> path declares that the repository for these family of components (in fact,  those starting with <tt>org.demo.</tt>) is in a CVS repository,  and that in fact these components are part of an eclipse project ("osgi.bundle, eclipse.feature, buckminster").
 +
##We do not want to commit changes back (<tt>mutable=false</tt>), and we do not want to extract source code (<tt>source=false</tt>).
 +
##The URI to a specific CVS repository is then given.
 +
##This URI ends with the name of the component. This name is obtained from the preset property <tt>buckminster.component</tt> which contains the name of the component being matched.
 +
#The <tt>maven</tt> path:
 +
##The <tt>maven</tt> path declares that it uses a maven provider; a <tt>readerType</tt> of maven, and that the <tt>componentType</tt> is also a maven component.
 +
##Like the <tt>default</tt> path,  we do not want to commit changes back (<tt>mutable=false</tt>), and we do not want to extract source code (<tt>source=false</tt>).
 +
##A URI to the maven repository at <tt>Ibiblio</tt> is declared.
 +
##A mapping that translates the component name into what the actual file on <tt>Ibiblio</tt> is called, is then declared (i.e. mapping <tt>se.tada.util.sax</tt> to <tt>tada-sax</tt>).
 +
 +
 +
So,  in summary,  to write an RMAP:
 +
#Identify a number of <tt>searchPaths</tt> which the RMAP can use.
 +
#For each <tt>searchPath</tt>,  give a <tt>locator</tt> string pattern matching the component names which you want to be found using this <tt>searchPath</tt>.  In fact you can define several <tt>locator</tt> string patterns,  so that several different sets of components can all be found using the same <tt>searchPath</tt>.
 +
#For each <tt>searchPath</tt>,  give one or more <tt>provider</tt>s.  Each <tt>provider</tt> should list its <tt>readerType</tt> (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 <tt>readerTypes</tt> for use within <tt>provider</tt> declarations are listed in the [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29#Provider_component Buckminster meta-data language guide].  They include for example <tt>CVS</tt>, <tt>Subversion</tt>, <tt>Maven</tt>, <tt>Perforce</tt> and <tt>site.feature</tt> amongst others.
 +
 +
<tt>componentTypes</tt> are required to configure the required <tt>readerType</tt>. The <tt>componentTypes</tt> indicates to the <tt>readerType</tt> which component structure and meta-data to expect for the declared <tt>provider</tt>. 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.
 +
 +
<tt>componentTypes</tt> must be referenced in this attribute by its fully qualified name. The full list of implementations of <tt>componentTypes</tt>s are also given in the [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29#Provider_component Buckminster meta-data language guide].  They include for example <tt>osgi.bundle</tt>, <tt>eclipse.feature</tt>, <tt>jar</tt> and <tt>maven</tt> amongst others.
 +
 +
=Publish an existing component=
 +
Buckminster provides two ways to publish an existing component:
 +
#Write a CQUERY, and associated RMAP,  as described above in the section [[#Materialize an existing component|Materialize an existing component]] above.  Publish the CQUERY so that others can use it,  as described also in the same section ''OR''
 +
#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|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 [[#Component Specifications (CSPECs)|below]]).
 +
 +
There are three basic steps to Buckminsterizing an entire Eclipse project containing plug-ins and features:
 +
#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.
 +
#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.
 +
#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.
 +
#Tell the others about your CQUERY XML file,  and have them open it in Eclipse using <tt>File > File Open</tt> or equivalent mechanisms as explained [[#Materialize an existing component|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):
 +
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
As you can see,  there are multiple CVS repositories for <tt>soas.features, soas.plugins, stp.sc, datatools.connectivity</tt> and <tt>b2j.plugins</tt>.  There are two locators for the <tt>stp.sc</tt> repository,  corresponding to two sets of components <tt>org.eclipse.stp.sc</tt> and <tt>org.eclipse.stp.common</tt>. 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 <tt>stp.rmap</tt>,  and then given to the corresponding simple CQUERY:
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
Once the materialisation completed,  the component <tt>org.eclipse.stp.soas.feature</tt> materialises into the current workspace.  Right-clicking on the package explorer view for the component throws up the usual <tt>Buckminster > Invoke Action..</tt> option.  Selecting the <tt>feature.exports</tt> 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
 +
<pre>
 +
buckminster.output.root=c:/temp/stp.build.output
 +
</pre>
 +
can be given to the <tt>Invoke Action..</tt> 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 [http://www.cloudsmith.com 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 [http://www.lomboz.com Lomboz] for <tt>Web Minimal for Windows, version 3.2.2.</tt>  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, <tt>com.eteration.lomboz4web-win32-minimal</tt>.  The CSPEC written for it is:
 +
<pre>
 +
<?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>
 +
</pre>
 +
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 <tt>com.eteration.lomboz4web-win32-minimal</tt>.
 +
* There is then a short textual description,  and some version information.  Versioning is described in more detail in [http://wiki.eclipse.org/Introduction_to_Buckminster#Versioning Why Buckminster? introduction] and there is a fuller description in the [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29 Buckminster meta-data language guide].
 +
* There then follow two dependencies:  the current component in turn depends on the components <tt>org.objectweb.lomboz.product.lomboz-all-in-one-win32</tt> and <tt>com.eteration.lomboz4web-platform-independent-minimal</tt>
 +
 +
More detailed examples of CSPECs [[#Component Specifications (CSPECs)|below]] if you are interested.
 +
 +
The component <tt>org.objectweb.lomboz.product.lomboz-all-in-one-win32</tt> in fact is materializable (ie it consists of binary and/or source).
 +
 +
The <tt>com.eteration.lomboz4web-platform-independent-minimal</tt> component is a virtual component. We have to write another component specification,  again as a CSPEC:
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
The <tt>apache-tomcat</tt> component is a materializable.
 +
 +
The <tt>com.eteration.lomboz-common</tt> component is another virtual component,  and here is the CSPEC written for it:
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
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.  [http://www.cloudsmith.com 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 (<tt>com.eteration.lomboz4web-win32-minimal</tt>) is:
 +
<pre>
 +
<?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>
 +
</pre>
 +
Note that an RMAP must be provided:  a sample RMAP is given later [[#The RMAP|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 [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29#Provider_component 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 [http://www.cloudsmith.com Cloudsmith] is one tool which can make this easy.
 +
 +
Resolving this query (using the usual approach,  see [[#Materialize_an_existing_component|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 <tt>com.eteration.lomboz4web-win32-minimal</tt> - 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:
 +
<pre>
 +
<?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>
 +
</pre>
 +
 +
 +
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 [http://www.cloudsmith.com Cloudsmith] is one tool which can make this easy.
 +
 +
 +
 +
 +
== Making use of an MSPEC to further simplify downloading ==
 +
As noted [[#The CQUERY|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:
 +
<pre>
 +
<?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>
 +
</pre>
 +
The MSPEC indicates that:
 +
* The materialisation should be done to the local folder <tt>c:/lomboz/install</tt>,  which is a <tt>filesystem</tt>,  and in general if there are conflicting components already installed on the destination machine,  then they should be <tt>REPLACE</tt>d with the new components being downloaded.
 +
* All downloaded components whose names match the pattern <tt>com.eteration.lomboz.*</tt> are virtual,  and are <tt>exclude</tt>d.
 +
* All downloaded components whose names match the pattern <tt>org.objectweb.lomboz.product.lomboz.*</tt> should go to the folder <tt>eclipse.zips/</tt> (under <tt>c:/lomboz/install/</tt>),  but replace any existing components of the same name only if the downloaded ones are more recent version.
 +
* Likewise <tt>myfaces-core, hibernate-core, spring-framework</tt> and <tt>struts</tt> to the folder <tt>frameworks.zips/</tt>;  and <tt>apache-tomcat</tt> to the folder <tt>servers.zips/</tt>
 +
 +
Note that the URL to the <tt>.bom</tt> file, generated (and saved) during query resolution should be inserted in the 6th line above for the <tt>url=</tt> value.
 +
 +
For more details of MSPECs, see the [http://wiki.eclipse.org/Buckminster_component_meta-data_language_1.0_%28Reference%29 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 <tt>File > New > Other > Buckminster > Component Specification file</tt>.
 +
 +
Sample CSPECs can be viewed by selecting <tt>File > View a selected CSPEC</tt> 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 <tt>artifact</tt> 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 <tt>'/'</tt>  after the name. The <tt><path></tt> sub-element can be used when more then one file or directory is desired; ''OR''
 +
*an <tt>action</tt> that describes something that can be carried out in order to produce zero or more new artifacts (ie files or directories); ''OR''
 +
*a <tt>group</tt>,  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 <tt>action</tt> attributes,  currently Buckminster only supports <tt>ant</tt> as an actor scripting language.  Parameters may be passed to the actor via <tt>actorProperties</tt> values (for example <tt>targets</tt> in the case of <tt>ant</tt> to describe the targets which <tt>ant</tt> should try to build). There are also certain "built-in" actions: <tt>eclipse.clean</tt> to request a clean build from the Eclipse build system;  <tt>eclipse.build</tt> to request a full build from the Eclipse build system;  and <tt>buckminster.prebind</tt>,  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):
 +
<pre>
 +
<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>
 +
</pre>
 +
 +
Here an artifact <tt>foo.jar</tt> denotes a single file located at <tt>../com.ics.jar</tt>,  which is of <tt>type bundle.jar</tt>.  If the <tt>base</tt> is omitted,  the name of the component (described by the CSPEC) is assumed.  The <tt>type</tt> field is essentially at this time only documentation, and serves no other purpose.  Because of the groups declaration,  the <tt>foo.jar</tt> artifact ends up in practice having two externally visible names: <tt>foo.jar</tt> and <tt>java.binaries</tt>.  The <tt>java.binaries</tt> is something that is intended to participate in a <tt>classpath</tt> that can be used by actions that are dependent on this
 +
component. The <tt>foo.jar</tt> is intended to be a packed bundle, suitable for an update site.
  
<p>In its simplest form, Buckminster is a tool for materializing a workspace. As
 
a component developer, your workspace is the set of components you are working
 
on plus all of their prerequisite components. Under Buckminster, components are
 
projects. In pictures, the workspace (the cloud) is initially empty, then you
 
ask Buckminster to materialize the component (the box), after which the workspace contains
 
the component:</p>
 
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image1.gif<br>
 
<i>(Bear with us on these pictures - right now they are trivial, but<br>
 
soon Buckminster's complexity will make the pictures useful.)</i></p>
 
<p>Because component A has pre-requisites B &amp; C which have prerequisites
 
themselves, the actual result is something like this:</p>
 
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image2.gif<br>
 
<i>Component A is the one you are working on;<br>
 
components B, C &amp; D are pre-reqs that must be in the workspace.</i></p>
 
  
==Where Does Buckminster Get Things?==
+
Consider another simple example (again, not a complete CSPEC):
<p>Once you've grasped that Buckminster&nbsp;materializes components, the next
+
<pre>
big questions in your mind is probably &quot;what are components?&quot; and
+
<cs:artifacts>
&quot;where does Buckminster get the components?&quot;. Components are
+
  <cs:private name="bundle.classpath" type="java.binaries">
collections of files (a.k.a. resources) and are represented in Eclipse by
+
    <cs:path path="resolver.jar"/>
projects. Components can be retrieved from a variety of different repositories.
+
    <cs:path path="xercesImpl.jar"/>
The most common repositories are a CVS repository or an FTP server, but almost
+
    <cs:path path="xml-apis.jar"/>
anything (databases, file systems, auto-generator programs, etc) can be used via
+
  </cs:private>
the <i>
+
</cs:artifacts>
org.eclipse.buckminster.core.readerTypes</i> extension point.</p>
+
<cs:groups>
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image3.gif<br>
+
  <cs:public name="java.binaries">
<i>Component A being retrieved from a CVS repository&nbsp;<br>
+
    <cs:attribute name="bundle.classpath"/>
and prerequisite component B from an FTP server.</i></p>
+
  </cs:public>
<p align="left">Of course the story is a bit more complicated than the simple
+
</cs:groups>
picture because the component retrieval takes into account various version
+
</pre>
naming schemes, but we'll get into that later. For now, this picture is good
+
enough.</p>
+
===How Does Buckminster Find The Repositories?===
+
<p>So the next question you're asking yourself is how does Buckminster know
+
which component is stored in which repository? Knowing what you know about
+
Eclipse, you know the projects are linked to Team (CVS) repositories. However
+
there are actually two concepts: the <i>component</i> and its <i>storage
+
location</i>. Separating these two concepts is like separating interface and
+
implementation in good software design. Buckminster does this separation through
+
a level of indirection known as a <i>resource map</i>. The resource map (rmap)
+
provides location information for families of components. When Buckminster needs
+
to load component A, it looks in the rmap to determine the repository containing
+
A, then goes to that repository and loads A. Then because A requires B and C,
+
Buckminster looks in the rmap for information on B and C, goes to those
+
repositories, loads those components, and so on.</p>
+
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image4.gif<br>
+
<i>The resource map maps components to storage locations.</i>
+
</p>
+
  
===Why Is The RMAP Useful?===
+
Here,  <tt>bundle.classpath</tt> and <tt>java.binaries</tt> are alternative names for the collection of files <tt>resolver.jar, xercesImpl.jar,</tt> and <tt>xml-apis.jar</tt>. However only <tt>java.binaries</tt> is visible as an attribute outside the CSPEC:  the attribute <tt>bundle.classpath</tt> is presumably used privately elsewhere within the (rest of the) CSPEC.
<p align="left">This separation of <i>component</i> and <i>storage location</i>
+
is useful because it allows Buckminster to retrieve the same component from
+
potentially many different storage locations. The rmap has a number of areas of
+
flexibility. First, the rmap defines storage locations for families of
+
components rather than single components. Thus one can say &quot;find all the
+
Apache components on the Apache ftp server&quot; without having to specify
+
&quot;find Apache Struts on the Apache ftp server and find Apache Cocoon on the
+
Apache ftp server and find ...&quot; ad nausea.&nbsp; Second, the rmap defines a
+
<i>search path</i> of storage locations to search for a component. Thus one can
+
say &quot;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&quot;.</p>
+
  
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image5.gif</p>
 
  
===One More Useful RMAP Feature===
+
=== A full example of a CSPEC ===
<p>Last, but not least, the rmap allows different search paths for different
+
Here is an example of a full CSPEC for a component called <tt>org.demo.worlds</tt>:
distributed development sites. Thus the rmap for Team Stockholm would list the
+
<pre>
same component families as the rmap for Team Winnipeg, but with different local
+
<?xml version="1.0" encoding="UTF-8"?>
repository servers.&nbsp; TCP round-trips from Canada to Sweden are slower than
+
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0" name="org.demo.worlds">
TCP round-trips from Canada to Canada, thus the Winnipeg team maintains a
+
    <cs:artifacts>
replicated CVS repository for certain components. </p>
+
    <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>
 +
</pre>
  
<p>Buckminster allows both teams to use the same rmap - the exact same file -
+
This meta-data describes the following:
but to define a different <i>site</i>, and thus a different set of search paths.
+
*The first two lines declare that this is XML; it follows the CSPEC format, and it describes a component called <tt>org.demo.worlds</tt>
Obviously the central servers (probably the last entry in each search path)
+
*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 <tt>source</tt>,  that is mapped to a folder called <tt>org.demo/worlds/src/</tt>
would point to the same central Swedish servers so that if the components were
+
*The next section lists the component attributes that are implemented as actions:
not cached locally, they would be fetched across the Atlantic.</p>
+
#The first action is <tt>java.binary.archives</tt>, and is publicly available to other CSPECs from this CSPEC.
 +
##It is implemented using an <tt>ant</tt> actor:  when <tt>ant</tt> is invoked by Buckminster as part of this particular action,  it is passed <tt>make/build.xml</tt> as the value of the standard <tt>buildFile</tt> parameter to <tt>ant</tt>.
 +
##The action has one prerequisite - the local (local to this CSPEC) action <tt>eclipse.build</tt> (see the next action in this CSPEC) which must be completed before this action can execute. This prerequisite also has an alias name <tt>input</tt> which can (only) be used within <tt>ant</tt> to refer to the same attribute <tt>eclipse.build</tt>.
 +
##The result of the action is a <tt>product</tt> in the file <tt>base bin/jars/worlds.jar</tt>;  <tt>ant</tt> can also reference this as <tt>output</tt>.
 +
#The second action is <tt>eclipse.build</tt>,  and is private (local) to this particular CSPEC.  Accessing this (action) attribute does not invoke an <tt>ant</tt> action but instead causes the Eclipse build system to run:
 +
##It has one prerequisite - the local (local to this CSPEC) attribute <tt>source/</tt> must exist:  from above, this tests that the folder <tt>src/</tt> exists.
 +
##The result of the action is a directory called <tt>bin/classes/.</tt>
 +
*Finally,  there is a publicly available (group) attribute called <tt>java.binaries</tt>,  which in fact is implemented by the single local action called <tt>eclipse.build</tt> described above:  the value of <tt>java.binaries</tt> is whatever <tt>eclipse.build</tt> generates.
  
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image6.gif<br>
+
In summary:  this CSPEC,  for a component called <tt>org.demo.worlds</tt> has three externally visible attributes:
<i>Winnipeg&nbsp; in purple, Stockholm in pink</i></p>
+
* <tt>source</tt>,  which in fact is the contents of the folder <tt>org.demo.worlds/src/</tt>;
 +
* <tt>java.binary.archives</tt>,  which in fact is the file <tt>org.demo.worlds/bin/jars/world.jar/</tt> but only available once generated by an <tt>ant</tt> actor,  and in turn only once the Eclipse build system has been called as a local action on this component;
 +
* <tt>java.binary</tt>,  which in fact is the directory <tt>org.demo.worlds/bin/classes/.</tt>,  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 <tt>org.eclipse.buckminster.core.feature</tt>:
 +
<pre>
 +
<?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>
 +
</pre>
  
===Back to Simplicity===
+
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 <tt>org.eclipse.buckminster.core.feature</tt>:
<p>We have described many useful features of the resource map, but to avoid cluttering the
+
* A private attribute <tt>build.properties</tt> located in the directory <tt>build.properties/</tt>
picture, let us retreat to the basics: the resource map (rmap) is mapping from <i>components
+
* A private attribute <tt>jar.contents</tt> which is the collection of files <tt>feature.properties, epl-v10.html, license.html</tt> and <tt>COPYRIGHT</tt>
</i>to <i>storage locations</i>.&nbsp;</p>
+
* A private attribute <tt>raw.manifest</tt> which is the file <tt>feature.xml</tt>
 +
* A public attribute <tt>buckminster.clean</tt> which is implemented as an <tt>ant</tt> actor, setting its <tt>buildFileId</tt> as <tt>buckminster.pdetasks</tt> and <tt>targets</tt> as <tt>delete.dir</tt>;  in addition <tt>${buckminster.output}</tt> is passed as the defined value (<tt>-Dprop=value</tt>) of <tt>dir.to.delete</tt> to <tt>ant</tt>.  There are however a number of prerequisites for this action:  the attribute <tt>buckminster.clean</tt> is accessed on each of the other components <tt>org.eclipse.buckminster.ui, org.eclipse.buckminster.cmdline, org.eclipse.buckminster.installer, org.eclipse.buckminster.runtime, org.eclipse.buckminster.ant, org.eclipse.buckminster.core</tt> and <tt>org.eclipse.buckminster.sax</tt>.  Note that there is no result or output from this action:  there is no <tt>products</tt> field.
 +
* A public attribute <tt>manifest</tt>, also implemented as an <tt>ant</tt> actor, setting its <tt>buildFileId</tt> as <tt>buckminster.pdetasks</tt> and its <tt>targets</tt> as <tt>expand.feature.version</tt>. The action has prerequisites - all of which are other attributes appearing elsewhere in the CSPEC (ie in the big list you are currently reading): <tt>raw.manifest</tt>,  also available as the name <tt>manifest</tt> to <tt>ant</tt>; <tt>bundle.jars</tt>, and as <tt>bundles</tt> to <tt>ant</tt>; <tt>feature.references</tt>, and as <tt>features</tt> to <tt>ant</tt>; and <tt>build.properties</tt>, as <tt>properties</tt> to <tt>ant</tt>.  It yields a result <tt>${buckminster.output}/temp/feature.xml</tt>, also known as <tt>action.output</tt> within <tt>ant</tt>.
 +
* A private attribute <tt>copy.features</tt>, implemented in <tt>ant</tt>, setting its <tt>buildFileId</tt> as <tt>buckminster.pdetasks</tt> and <tt>targets</tt> as <tt>copy.group</tt>.  It has one prerequisite attribute (appearing elsewhere in the CSPEC) called <tt>feature.jars</tt>, known as <tt>action.requirements</tt> to <tt>ant</tt>.  Its value is the contents of <tt>${buckminster.output}/site/features/</tt>,  also known as <tt>action.output</tt> to <tt>ant</tt>.  However,  the action has an <tt>uptoDatePolicy</tt> setting, an optimisation hint which may reduce the work Buckminster needs to do.  The <tt>MAPPER</tt> setting compares the <tt>product</tt> with each corresponding prerequsite:  if there is match and the <tt>product</tt> is younger than the <tt>prerequisite</tt> then the action can be skipped, since the results of the action were previously done and are already in place.
 +
* A private attribute <tt>copy.plugins</tt>,  similar in style to the <tt>copy.features</tt> attribute above.
 +
* A private attribute <tt>feature.jar</tt>, somewhat similar in style to both the <tt>copy.features</tt> and <tt>copy.plugins</tt> above.  However the <tt>uptToDatePolicy</tt> optimistion hint is set to <tt>COUNT</tt> and with <tt>fileCount=1</tt>,  meaning that the action can be skipped as unnecessary if at least one file in the <tt>products ${buckminster.output}/jar/</tt> is younger than the youngest artifact found in the <tt>prerequisites mainfest</tt> and <tt>jar.contents</tt>
 +
* A public attribute <tt>bundle.jars</tt> which is the collection of all the <bundle.jar> attributes of each of each of the other components <tt>org.eclipse.buckminster.ui, org.eclipse.buckminster.cmdline, org.eclipse.buckminster.installer, org.eclipse.buckminster.runtime, org.eclipse.buckminster.ant, org.eclipse.buckminster.core</tt> and <tt>org.eclipse.buckminster.sax</tt>.
 +
* A public attribute <tt>feature.exports</tt>,  which is both of the (private) attibutes <tt>copy.features</tt> and <tt>copy.plugins</tt> as above,  but with the directory <tt>${buckminster.output}/site/</tt> overriding the <tt>base</tt> directory settings in those two attributes.
 +
* A public attribute <tt>feature.jars</tt>,  which is the pair of attributes <tt>feature.jar</tt> and <tt>feature.references</tt>.
 +
* Two public attributes <tt>feature.references</tt> and <tt>product.root.files</tt>,  which in fact are both dummy attributes having no value,  and placeholders -- this is a generated CSPEC.
  
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image4.gif</p>
+
My coffee is cold, time for another.
<p align="left">For details of the rmap XML schema, see <a href="rmap.html">the
+
reference manual</a>.</p>
+
  
==What is a Component?==
+
<p>A <i>component</i>, in the Buckminster parlance, is a collection of files or
+
sometimes one single file. For most Buckminster users, a component is an Eclipse project, but
+
components are a larger concept than that - components can be external to
+
==Extended Component Specifications (CSPEXs)==
Eclipse, components can have sub-components, etc.</p>
+
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 <tt>buckminster.cspex</tt>, which must be placed into the same directory/folder as the component itself, and which follows the general CSPEC format.
  
===Components Do Not Stand Alone: Dependencies===
+
In general,  a <tt>CSPEX</tt> enables you to manually extend, and add to, automatically generated <tt>CSPEC</tt> files with further metadata that is not readily deducible by Buckminster.
<p>Components may depend on other components but a fundamental concept in
+
Buckminster is that it's not until you do something with a component that the
+
dependencies arise. Depending on what you do, you might need different things.
+
Buckminster will separate the actions (what you do) from the dependencies (what
+
you need). The actions are described in an Action Specification (aspec). This
+
will be covered later. The dependencies are described in the Dependency
+
Specification (dspec). The <i>dspec</i> describes all dependencies without
+
respect to what actions that should be performed.</p>
+
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image8.gif<br>
+
<i>A component has zero or more dependencies</i></p>
+
<p>Obviously Buckminster finds the closure of the dependency graph when it
+
materializes a workspace. The closure will always be in the form of a Directed
+
Acyclic Graph (DAG). In our pictorial example, component A requires
+
components B and C, and component B requires component D, and component C
+
requires component D, so when Buckminster will load all four into the workspace.</p>
+
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image9.gif</p>
+
  
===Versioned Dependencies===
+
Here is an example, from the [http://wiki.eclipse.org/index.php/Hello_XML_World_Example_%28Buckminster%29 Hello World] example, and reproduced below for convenience:
<p>Software has always been a challenging field because, unlike the continuous
+
<pre>
(or analog) nature of the real world, software is discrete (or digital). Thus a
+
<?xml version="1.0" encoding="UTF-8"?>
feature that worked in version 4.5 of the system may no longer work in version
+
<cs:cspecExtension
5.0 or even in 4.6 or even in 4.5.1. Thus cspec dependencies include a version
+
  xmlns:com="http://www.eclipse.org/buckminster/Common-1.0"
matching clause.</p>
+
  xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0">
<p>There are two pieces of a version match clause:</p>
+
  <cs:dependencies>
<ol>
+
    <cs:dependency name="org.demo.worlds"/>
  <li>The version string</li>
+
    <cs:dependency name="se.tada.util.sax"  versionDesignator="1.0.0" versionType="OSGi"/>
  <li>The version type</li>
+
  </cs:dependencies>
</ol>
+
<p>Normally, the version string would be something simple like &quot;4.5&quot;. However,
+
because Buckminster is designed for and by software developers, and because
+
software is not developed in a linear fashion, the version string is more
+
complex (and more useful) than the simple &quot;4.5&quot;. Specifically, the version
+
string can denote a range. The characters '[' and ']' are used to denote an
+
inclusive range and the characters '(' and ')' will denote an exclusive range.
+
Here are some examples:</p>
+
<div align="center">
+
<table>
+
<th>Example</th><th>&nbsp;</th><th>Predicate</th>
+
<tr><td>[1.2.3, 4.5.6)</td><td>&nbsp;</td><td>1.2.3 &lt;= x &lt; 4.5.6</td></tr>
+
<tr><td>[1.2.3, 4.5.6]</td><td>&nbsp;</td><td>1.2.3 &lt;= x &lt;= 4.5.6</td></tr>
+
<tr><td>(1.2.3, 4.5.6)</td><td>&nbsp;</td><td>1.2.3 &lt; x &lt; 4.5.6</td></tr>
+
<tr><td>(1.2.3, 4.5.6]</td><td>&nbsp;</td><td>1.2.3 &lt; x &lt;= 4.5.6</td></tr>
+
<tr><td>1.2.3</td><td>&nbsp;</td><td>1.2.3 &lt;= x</td></tr>
+
</table>
+
</div>
+
<p align="center"><i>Examples of version ranges.</i></p>
+
<p>Buckminster is not limited to the major.minor.micro number notation used in
+
this example. That notation is just one of several possible notations. Each
+
notation corresponds to a <i>version type</i>.&nbsp; The type interprets the
+
version token(s) of a range and assings a magnitude to the result so that
+
versions can be compared. Buckminster allow new types to be added dynamically.</p>
+
  
===Mapping Versions to a Revision Control System===
+
  <cs:actions>
<p>The versions used in the dependency specification will often be meaningless
+
    <cs:public name="buckminster.prebind" actor="ant">
to a revision control system. Buckminster will therefore use a Version
+
      <cs:actorProperties>
Converter. It is the responsability of the converter to create something that a
+
<cs:property key="buildFile" value="make/prebind.xml" />
revision control system can understand. The converter will also be able to
+
      </cs:actorProperties>
convert in the other direction and it plays a very important role when the best
+
      <cs:prerequisites>
match for a version string is to be found in a revision control system. The
+
        <cs:attribute component="se.tada.util.sax" alias="tada-sax.jar" name="java.binary.archives"/>
version will typically be converted into branches and tags.</p>
+
<cs:attribute component="org.demo.worlds" alias="worlds.jar" name="java.binary.archives"/>
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image10.gif<br>
+
      </cs:prerequisites>
<i>Branches and versions of component C that one might find in a revision control system.</i></p>
+
      <cs:products alias="output">
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image11.gif<br>
+
        <cs:path path="jars/" />
<i>Component A depends on the specific<br>
+
      </cs:products>
version &quot;main/2.0&quot; of component C</i></p>
+
    </cs:public>
<p align="center"><i>TODO: Fix this image. Branch/Tag combinations are not
+
  </cs:actions>
typcial in the dspec.</i></p>
+
</cs:cspecExtension>
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image12.gif<br>
+
</pre>
<i>The component DAG with explicit branch specifiers on each depedency.</i></p>
+
  
===The Simplest Case of Versions===
+
This extension works as follows:
<p>The simplest version numbering (branch specifications) is the linear version
+
* Lines 1-4 are the XML content and declarations of namespaces. Note the use of a <tt>cspecExtension</tt> element as the top most element.
numbers: 1.0, 1.1, 1.2, 2.0, etc. Linear version numbers are the base case: a
+
* Next, two dependencies are listed for the current component, on both components <tt>org.demo.worlds</tt> and <tt>se.tada.util.sax</tt>.  Buckminster needs to find both before the current component can be processed.
revision control system with just one main branch.</p>
+
* The <tt>actions</tt> section declares a private (local to this CSPEX) action <tt>buckminster.prebind</tt> as an <tt>ant</tt> action. As for CSPECs, the name <tt>buckminster.prebind</tt> 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 <tt>ant</tt> actor is passed <tt>make/prebind.xml</tt> as the value of its <tt>buildFile</tt> parameter.
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image13.gif<br>
+
* There are two pre-requisites to the action.
<i>Component B has one main branch, the &lt;default&gt; branch.</i></p>
+
# The first is on attribute <tt>java.binary.archives</tt> in the component <tt>se.tada.util.sax</tt>,  and is known within the <tt>ant</tt> script as <tt>tada-sax.jar</tt>.
<p>When the component dependencies have no branch specifier, Buckminster uses <code>&lt;default&gt;/LATEST</code>
+
# The second is on the attribute <tt>java.binary.archives</tt> in the component <tt>org.demo.worlds</tt>, and is also known within the <tt>ant</tt> script as <tt>worlds.jar</tt>.
which translates to &quot;the latest version of the default branch&quot;. The
+
* The <tt>products</tt> section declares that the result is known as <tt>output</tt> to the <tt>ant</tt> script, and is produced in the folder <tt>jars/.</tt>
default branch varies by revision control system: CVS uses &quot;HEAD&quot;, SVN
+
uses &quot;trunk&quot;,
+
ClearCase uses &quot;main&quot;, etc.</p>
+
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image9.gif<br>
+
<i>Component A's dependency on component B has no branch&nbsp;<br>
+
specifier, thus Buckminster uses B:&lt;default&gt;/LATEST</i></p>
+
<p>If the cspec dependency includes a version number, Buckminster uses a <i>version
+
converter </i>to translate the version number into a branch specification. The
+
most common translation is &quot;version&quot; into
+
&quot;&lt;default&gt;/version&quot;. For example:</p>
+
<p align="center">http://www.eclipse.org/buckminster/drafts/images/image14.gif<br>
+
<i>Component A's dependency on component B is version &quot;2.0&quot;<br>
+
which gets translated to &quot;&lt;default&gt;/2.0&quot;. Similarly, the
+
dependency<br>
+
on component C is &quot;1.1&quot; which gets translated as
+
&quot;&lt;default&gt;/1.1&quot;.<br>
+
Looking at the branching diagram above, we see that &quot;&lt;default&gt;&quot;
+
is<br>
+
&quot;main&quot;, thus Buckminster will load &quot;main/1.1&quot; to satisfy
+
that dependency.</i></p>
+
  
===What If There Isn't a Revision Control System?===
 
<p>What if the component is not stored in a revision control system? For
 
example, what if the component is stored in an FTP directory? The answer is that
 
the <i>providers </i>and <i>component readers </i>defined in the rmap handle
 
reading versioned components from the appropriate repository. If the repository
 
does not provide versions, then the component reader treats the repository as if
 
it has just one version: <kbd>&lt;default&gt;/LATEST</kbd>. Requesting any other
 
branch specification will fail.</p>
 
<p>Or, to put the situation more positively, Buckminster treats a &quot;no
 
revision control system&quot; situation as a simple revision control system that
 
provides only one branch and one version.</p>
 
  
===The Flexible Case of Versions===
+
[[Category:Buckminster]]
<p>MOREMORE other tag naming</p>
+
[[Category:Buckminster Introduction]]
<p>MOREMORE resource maps, search-paths, providers.</p>
+
<p>MOREMORE ref earlier pictures</p>
+
<p>MOREMORE picture of A, B, C, D with complex labels</p>
+
<p>MOREMORE <i>
+
org.eclipse.buckminster.core.componentTypes and dynamic cspecs</i></p>
+
<p>MOREMORE component queries</p>
+
<p>MOREMORE action specs</p>
+

Latest revision as of 19:05, 14 February 2009

< 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/.

Back to the top