Difference between revisions of "IAM Buckminster Integration"

From Eclipsepedia

Jump to: navigation, search
(Undo revision 251167 by Simon.atkins06.gmail.com (Talk))
 
Line 36: Line 36:
 
* Right click on a project managed by IAM (if a project has a pom.xml you can set it to be IAM-managed by right-clicking on it and toggling on the "Use Maven dependency management" option in the "Maven 2" sub-menu). Choose the "Materialize dependencies..." option in the "Maven 2" sub-menu.
 
* Right click on a project managed by IAM (if a project has a pom.xml you can set it to be IAM-managed by right-clicking on it and toggling on the "Use Maven dependency management" option in the "Maven 2" sub-menu). Choose the "Materialize dependencies..." option in the "Maven 2" sub-menu.
  
* A dialog will appear containing a list with those dependencies with a <scm> tag in their corresponding pom.xml's (more precisely, the <scm> tag must contain the <connection> tag for the dependency to be taken into account: obviously the <span class="plainlinks">[http://www.OutdoorFountains.com <span style="color:black;font-weight:normal;text-decoration:none!important; background:none!important;text-decoration:none;">outdoor fountains</span>] plug-in needs to know where it must look for the dependency code ). Choose whatever dependencies you need to be materialized and click the OK button.
+
* A dialog will appear containing a list with those dependencies with a <scm> tag in their corresponding pom.xml's (more precisely, the <scm> tag must contain the <connection> tag for the dependency to be taken into account: obviously the plug-in needs to know where it must look for the dependency code ). Choose whatever dependencies you need to be materialized and click the OK button.
  
  

Latest revision as of 09:24, 19 May 2011

< To: IAM

Contents

[edit] Introduction

Buckminster integration allows IAM users to materialize Maven dependencies in their Eclipse workspace. That means that the user is provided with a Maven project's list of dependencies and he/she can select which of them will be materialized in his/her workspace as Eclipse projects.

[edit] What is Buckminster

Buckminster is a component resolution and materialization framework presented as a plugin for Eclipse. For detailed information about this technology, please visit the Buckminster Project wiki.

[edit] Why do you need this plug-in?

Well, you might not need it at all... if the projects you work in are self-contained. If that's not the case, you may need to work with your project's dependencies' sources and that means you must find where are those sources (we hope they're under version control), check them out and import them as Eclipse projects. Don't you think it would be better to drink a cup of coffee instead and let IAM do this for you?

[edit] IAM Buckminster integration features

  • Works with the Buckminster plug-in to materialize Maven dependencies. This allows us to rely on Buckminster's repository access and component materialization capabilities, being relatively easy for us to add support to new SCM systems in the future (as far as Buckminster supports them).
  • Right now, it allows the dependencies to be located in Subversion or CVS repositories, which should be enough for the most of users (at least we hope so).
  • Some degree of inexactness is allowed to a dependency's SCM information. That means that the plug-in will try several locations for a dependency (based on heuristics taken from real-world examples) if it cannot infer its exact location from the pom.xml.

[edit] User guide

[edit] Installation

Buckminster Feature needs Buckminster Core 1.1.0 and ECF 2.0. There's no problem installing this feature in eclipse 3.4 since the dependencies are automatically resolved from eclipse repositories if it's not yet in your eclipse 3.4 plugins.

But in eclipse 3.3, you need to explicitly download the dependencies.

Buckminster 1.1.0 can be downloaded from http://download.eclipse.org/tools/buckminster/updates updatesite. ECF 2.0 can be downloaded from http://download.eclipse.org/rt/ecf/2.0/updateSite updatesite.

Buckminster dependencies.jpg

[edit] The user interface

Anyone can use the IAM-Buckminster Integration core in his/her own plug-ins, but we're also providing a default user interface, and this section will show you how to use it. To start materializing Maven dependencies you only need to follow this instructions:

  • Right click on a project managed by IAM (if a project has a pom.xml you can set it to be IAM-managed by right-clicking on it and toggling on the "Use Maven dependency management" option in the "Maven 2" sub-menu). Choose the "Materialize dependencies..." option in the "Maven 2" sub-menu.
  • A dialog will appear containing a list with those dependencies with a <scm> tag in their corresponding pom.xml's (more precisely, the <scm> tag must contain the <connection> tag for the dependency to be taken into account: obviously the plug-in needs to know where it must look for the dependency code ). Choose whatever dependencies you need to be materialized and click the OK button.


IAMBuckminster MaterializeDependenciesDialog.png


  • A CQUERY and a RMAP will be generated for each dependency (for details about CQUERYs and RMAPs please visit the Buckminster Project wiki) and Buckminster will try to materialize them. Be patient and, if nothing bad happens, the selected dependencies will appear as Eclipse projects in your workspace. (Right now, the feedback provided by the IAM Buckminster integration plug-in is almost non-existent, so if you need verbose information about what's happening during the materialization process you should go to the Eclipse preferences, then to the Buckminster section and set the console logger level as DEBUG).

[edit] Subversion

We'll show you now the preferred layouts for Subversion connection strings. If your dependencies' pom.xml's contain the following kind of strings in the <connection> tag, there shouldn't be any problem to materialize them:

  • In the string, the dependency's artifactId appears before the tags directory and after the tags directory appears a tag. For example:
<scm>
  <connection>scm:svn:http://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_14</connection>
</scm>

From this SCM (knowing that the dependency we're looking for has the "log4j" artifactId) we can extract the connection string (http://svn.apache.org/repos/asf/logging/log4j/trunk) and the tag we must look for (v1_2_14). This would be as good:

<scm>
  <connection>scm:svn:http://svn.apache.org/repos/asf/logging/log4j/tags</connection>
  <tag>v1_2_14</tag>
</scm>

Here we can just take the tag from the <tag> tag :-)

  • In the string we have the tags directory first, then the artifactId (ArturusCore in the next example) and finally the tag:
<scm>
  <connection>scm:svn:http://my.local.server/svn/tags/ArturusProject/ArturusCore/arturus-core-1.2.0</connection>
</scm>

From this SCM we can extract the connection string http://my.local.server/svn/trunk/ArturusProject/ArturusCore?moduleBeforeTag. Also, as in the first case, this will be equally ok:

<scm>
  <connection>scm:svn:http://my.local.server/svn/tags/ArturusProject/ArturusCore</connection>
  <tag>arturus-core-1.2.0</tag>
</scm>
  • By the way, if there's no tags nor branches directory in the connection string, we'll go for the trunk.

If everything fails the plug-in will try some heuristics, which are described here.

[edit] CVS

The plug-in transforms CVS connection strings with this layout scm:cvs:pserver:user@server:/path:projectName into this: :pserver:user@server:/path,projectName, which Buckminster understands. For example:

<scm>
  <connection>scm:cvs:pserver:anonymous@cvs.sourceforge.net:/cvsroot/dom4j:dom4j</connection>
</scm>

The connection contained in this SCM information would be converted into :pserver:anonymous@dom4j.cvs.sourceforge.net:/cvsroot/dom4j,dom4j. You might say: what about the tags? Yes, that's a little problem. If the optional <tag> tag isn't available, we must rely in some heuristics, which we'll explain in the next section.

[edit] Heuristics

When the IAM Buckminster integration plug-in cannot directly obtain the tag where a dependency is located, it tries to find it by transforming the dependency version using several "popular" (seen in the real world) tag naming conventions. Right now, these are the implemented transformations (for example, "1.2.3 => one-two-three" means "version 1.2.3 becomes tag one-two-three"):

  • 1.2 => 1.2 and 1.2.3 => 1.2.3
  • 1.2 => v1_2 and 1.2.3 => v1_2_3
  • 1.2 => v_1_2 and 1.2.3 => v_1_2_3
  • 1.2.3 => artifactId_1_2_3
  • 1.2 => RELEASE-1_2 and 1.2.3 => RELEASE-1_2_3 (being RELEASE case-insensitive)

This transformations are described with regular expressions within the generated RMAPs. So, if you need a certain transformation, and you are not easily scared by regular expressions, the following section might be of your interest.

[edit] Adding new version transformations

We have defined an extension point (which will be available soon) called org.eclipse.iam.buckminster.core.rmaptransformations which anyone can use to add new version transformations to the IAM-Buckminster plugin. It's very easy! (well, as easy as regular expressions can be). In the screenshot you can see a detail of the default transformations which come with the plug-in:


IAM-Buckminster extension point screenshot.jpg


As you can see, you can define a series of transform elements formed by several versionConverter elements (each of them defined by the obligatory fields fromPattern, fromReplacement, toPattern and toReplacement). Details about transform and versionConverter elements can be found in the Buckminster wiki, here

You can use the Eclipse editor to define the transformations, or you can just play a little with the plugin.xml. Here is the xml fragment corresponding to the previous image:

<extension point="org.eclipse.iam.buckminster.core.rmaptransformations">
      <transform>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)$"
               fromReplacement="v$1_$2"
               toPattern="^v(\d+)_(\d+)$"
               toReplacement="$1\.$2">
         </versionConverter>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)\.(\d+)$"
               fromReplacement="v$1_$2_$3"
               toPattern="^v(\d+)_(\d+)_(\d+)$"
               toReplacement="$1\.$2\.$3">
         </versionConverter>
      </transform>
      <transform>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)$"
               fromReplacement="v_$1_$2"
               toPattern="^v_(\d+)_(\d+)$"
               toReplacement="$1\.$2">
         </versionConverter>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)\.(\d+)$"
               fromReplacement="v_$1_$2_$3"
               toPattern="^v_(\d+)_(\d+)_(\d+)$"
               toReplacement="$1\.$2\.$3">
         </versionConverter>
      </transform>
      <transform>
         <versionConverter
               fromPattern="^(.*)$"
               fromReplacement="${artifactId}_$1"
               toPattern="^${artifactId}_(.*)$"
               toReplacement="$1">
         </versionConverter>
         <versionConverter
               fromPattern="^${artifactId}_$"
               fromReplacement="${artifactId}\."
               toPattern="^${artifactId}\.$"
               toReplacement="${artifactId}_">
         </versionConverter>
         <versionConverter
               fromPattern="\."
               fromReplacement="_"
               toPattern="_"
               toReplacement="\.">
         </versionConverter>
      </transform>
      <transform>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)$"
               fromReplacement="RELEASE-$1_$2"
               toPattern="^((?i)(RELEASE))-(\d+)_(\d+)$"
               toReplacement="$3\.$4">
         </versionConverter>
         <versionConverter
               fromPattern="^(\d+)\.(\d+)\.(\d+)$"
               fromReplacement="RELEASE-$1_$2_$3"
               toPattern="^((?i)(RELEASE))-(\d+)_(\d+)_(\d+)$"
               toReplacement="$3\.$4\.$5">
         </versionConverter>
      </transform>
   </extension>

You can reference a Maven artifact's artifactId or groupId by placing the ${artifactId} or ${groupId} strings in a regular expression and the plug-in will replace them with the appropriate values.

[edit] How it works

This section aims to explain (more or less) how the IAM Buckminster integration works, but it's not necessary for the user to read it. Also, it's highly recommended to have some basic knowledge about the Buckminster plug-in to better understand the following.

[edit] An example

Let's consider a Maven project like log4j. Its SCM information (extracted from the log4j version 1.2.14 pom.xml) looks like this:

<scm>
  <connection>scm:svn:http://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_14</connection>
  <developerConnection>scm:svn:https://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_14</developerConnection>
  <url>http://svn.apache.org/viewcvs.cgi/logging/log4j/tags/v1_2_14/</url>
</scm>

Now, if log4j version 1.2.14 is one of the dependencies you choose to materialize, the IAM Buckminster integration plug-in will generate the following RMAP and CQUERY:

<rmap xmlns="http://www.eclipse.org/buckminster/RMap-1.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" 
      xmlns:mp="http://www.eclipse.org/buckminster/MavenProvider-1.0">
  <searchPath name="log4j">
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
      <versionConverter type="tag" versionType="String">
        <transform fromPattern="^(.+)$" fromReplacement="$1" toPattern="^(.+)$" toReplacement="$1"/>
      </versionConverter>
    </provider>
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
      <versionConverter type="tag" versionType="String">
        <transform fromPattern="^(\d+)\.(\d+)$" fromReplacement="v$1_$2" 
                   toPattern="^v(\d+)_(\d+)$" toReplacement="$1\.$2"/>
        <transform fromPattern="^(\d+)\.(\d+)\.(\d+)$" fromReplacement="v$1_$2_$3" 
                   toPattern="^v(\d+)_(\d+)_(\d+)$" toReplacement="$1\.$2\.$3"/>
      </versionConverter>
    </provider>
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
      <versionConverter type="tag" versionType="String">
        <transform fromPattern="^(\d+)\.(\d+)$" fromReplacement="v_$1_$2" 
                   toPattern="^v_(\d+)_(\d+)$" toReplacement="$1\.$2"/>
        <transform fromPattern="^(\d+)\.(\d+)\.(\d+)$" fromReplacement="v_$1_$2_$3" 
                   toPattern="^v_(\d+)_(\d+)_(\d+)$" toReplacement="$1\.$2\.$3"/>
      </versionConverter>
    </provider>
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
      <versionConverter type="tag" versionType="String">
        <transform fromPattern="^(.*)$" fromReplacement="log4j_$1" toPattern="^log4j_(.*)$" toReplacement="$1"/>
        <transform fromPattern="^log4j_$" fromReplacement="log4j\." toPattern="^log4j\.$" toReplacement="log4j_"/>
        <transform fromPattern="\." fromReplacement="_" toPattern="_" toReplacement="\."/>
      </versionConverter>
    </provider>
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
      <versionConverter type="tag" versionType="String">
        <transform fromPattern="^(\d+)\.(\d+)$" fromReplacement="RELEASE-$1_$2" 
                   toPattern="^((?i)(RELEASE))-(\d+)_(\d+)$" toReplacement="$3\.$4"/>
        <transform fromPattern="^(\d+)\.(\d+)\.(\d+)$" fromReplacement="RELEASE-$1_$2_$3" 
                   toPattern="^((?i)(RELEASE))-(\d+)_(\d+)_(\d+)$" toReplacement="$3\.$4\.$5"/>
      </versionConverter>
    </provider>
  </searchPath>
  <locator searchPathRef="log4j" pattern="log4j"/>
</rmap>
<componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0"
                resourceMap="file:///home/superman/workspace/iam_rmap_log4j_999.rmap">
  <rootRequest name="log4j" componentType="unknown" versionDesignator="[v1_2_14,v1_2_14]" versionType="String"/>
</componentQuery>

With this two things (RMAP and CQUERY) we can now call Buckminster and ask it to materialize log4j into the user's workspace. We'll explain now some details about the generated CQUERY and RMAP:

  • The CQUERY (component query) has a pointer to the generated RMAP (we assume its location is /home/superman/workspace/iam_rmap_log4j_999.rmap) and requests the log4j component. There's some extra information: the component type is set to unknown because we don't need Buckminster to calculate log4j's dependencies; the version designator is [v1_2_14,v1_2_14] because we're looking for a certain version of log4j, and no other; and finally, the version type is String so we're taking the alphanumerical order to compare different versions.
  • Why is the version designator set to [v1_2_14,v1_2_14] and not to [1.2.14,1.2.14]? Even when the second seems more logical, we know in this case which tag corresponds to the dependency version (we inferred it from the <connection>scm:svn:http://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_14</connection> tag) so we can ask Buckminster to look for the code contained in the Subversion repository tag v1_2_14 instead of relying in the transformations we'll talk about later (which are described in the RMAP). By the way, we know the SCM system used by the log4j project is Subversion because of the scm:svn fragment in the connection string.
  • The RMAP describes one search path which corresponds with the log4j component. This search path points to http://svn.apache.org/repos/asf/logging/log4j/trunk, a URL which was obtained from the http://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_14 URL in the connection tag. Buckminster only recognizes Subversion connections to the trunk path, so this transformation must be performed. But the first URL contains a tags directory, so we're looking for a tag, not for the trunk. This must be configured in the RMAP with the help of the version converters. Apart from telling Buckminster that we want a tag, version converters can describe version transformations.
  • What are transformations good for? If the IAM Buckminster integration plug-in cannot infer which tag inhabits the component we want, it tries to find it transforming its version. For example, we're looking for the version 1.2.14 of log4j, and if we didn't know it is located in the v1_2_14 tag, we'd try to find it in the v_1_2_14, log4j-1_2_14, release-1_2_14, ... tags. These are some of the transformations defined in the RMAP (there's also a transformation which doesn't change anything which works when we know exactly where tag to look in). Transformations are specially important if we're working with CVS (we never can infer the exact tag where a component is located when we use CVS because the connection strings are like this: scm:cvs:pserver:anonymous@cvs.sourceforge.net:/cvsroot/easyconf:easyconf).
  • By the way, if we were looking for the trunk of log4j and not for a tag, the generated RMAP would be as simple as this:
<rmap xmlns="http://www.eclipse.org/buckminster/RMap-1.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" 
      xmlns:mp="http://www.eclipse.org/buckminster/MavenProvider-1.0">
  <searchPath name="log4j">
    <provider readerType="svn" componentTypes="unknown" source="true">
      <uri format="http://svn.apache.org/repos/asf/logging/log4j/trunk"/>
    </provider>
  </searchPath>
  <locator searchPathRef="log4j" pattern="log4j"/>
</rmap>