Coverage Report - org.apache.maven.plugin.eclipse.EclipseToMavenMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
EclipseToMavenMojo
100%
51/51
N/A
4.706
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.maven.plugin.eclipse;
 20  
 
 21  
 import java.io.File;
 22  
 import java.io.FileOutputStream;
 23  
 import java.io.IOException;
 24  
 import java.io.OutputStreamWriter;
 25  
 import java.io.Writer;
 26  
 import java.util.ArrayList;
 27  
 import java.util.HashMap;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.regex.Matcher;
 32  
 import java.util.regex.Pattern;
 33  
 
 34  
 import aQute.lib.osgi.Analyzer;
 35  
 
 36  
 import org.apache.maven.artifact.Artifact;
 37  
 import org.apache.maven.artifact.deployer.ArtifactDeployer;
 38  
 import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
 39  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 40  
 import org.apache.maven.artifact.installer.ArtifactInstallationException;
 41  
 import org.apache.maven.artifact.installer.ArtifactInstaller;
 42  
 import org.apache.maven.artifact.metadata.ArtifactMetadata;
 43  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 44  
 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
 45  
 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
 46  
 import org.apache.maven.model.Dependency;
 47  
 import org.apache.maven.model.License;
 48  
 import org.apache.maven.model.Model;
 49  
 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
 50  
 import org.apache.maven.plugin.AbstractMojo;
 51  
 import org.apache.maven.plugin.MojoExecutionException;
 52  
 import org.apache.maven.plugin.MojoFailureException;
 53  
 import org.apache.maven.plugin.eclipse.osgiplugin.EclipseOsgiPlugin;
 54  
 import org.apache.maven.plugin.eclipse.osgiplugin.ExplodedPlugin;
 55  
 import org.apache.maven.plugin.eclipse.osgiplugin.PackagedPlugin;
 56  
 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
 57  
 import org.codehaus.plexus.PlexusConstants;
 58  
 import org.codehaus.plexus.PlexusContainer;
 59  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 60  
 import org.codehaus.plexus.components.interactivity.InputHandler;
 61  
 import org.codehaus.plexus.context.Context;
 62  
 import org.codehaus.plexus.context.ContextException;
 63  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 64  
 import org.codehaus.plexus.util.IOUtil;
 65  
 import org.codehaus.plexus.util.StringUtils;
 66  
 
 67  
 /**
 68  
  * Add eclipse artifacts from an eclipse installation to the local repo. This mojo automatically analize the eclipse
 69  
  * directory, copy plugins jars to the local maven repo, and generates appropriate poms. This is the official central
 70  
  * repository builder for Eclipse plugins, so it has the necessary default values. For customized repositories see
 71  
  * {@link MakeArtifactsMojo} Typical usage:
 72  
  * <code>mvn eclipse:to-maven -DdeployTo=maven.org::default::scpexe://repo1.maven.org/home/maven/repository-staging/to-ibiblio/eclipse-staging -DeclipseDir=.</code>
 73  
  * 
 74  
  * @author Fabrizio Giustina
 75  
  * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
 76  
  * @version $Id: EclipseToMavenMojo.java 598543 2007-11-27 07:44:51Z carlos $
 77  
  * @goal to-maven
 78  
  * @requiresProject false
 79  
  */
 80  15
 public class EclipseToMavenMojo
 81  
     extends AbstractMojo
 82  
     implements Contextualizable
 83  
 {
 84  
 
 85  
     /**
 86  
      * A pattern the <code>deployTo</code> param should match.
 87  
      */
 88  1
     private static final Pattern DEPLOYTO_PATTERN = Pattern.compile( "(.+)::(.+)::(.+)" );
 89  
 
 90  
     /**
 91  
      * A pattern for a 4 digit osgi version number.
 92  
      */
 93  1
     private static final Pattern VERSION_PATTERN = Pattern.compile( "(([0-9]+\\.)+[0-9]+)" );
 94  
 
 95  
     /**
 96  
      * Plexus container, needed to manually lookup components for deploy of artifacts.
 97  
      */
 98  
     private PlexusContainer container;
 99  
 
 100  
     /**
 101  
      * Local maven repository.
 102  
      * 
 103  
      * @parameter expression="${localRepository}"
 104  
      * @required
 105  
      * @readonly
 106  
      */
 107  
     private ArtifactRepository localRepository;
 108  
 
 109  
     /**
 110  
      * ArtifactFactory component.
 111  
      * 
 112  
      * @component
 113  
      */
 114  
     private ArtifactFactory artifactFactory;
 115  
 
 116  
     /**
 117  
      * ArtifactInstaller component.
 118  
      * 
 119  
      * @component
 120  
      */
 121  
     protected ArtifactInstaller installer;
 122  
 
 123  
     /**
 124  
      * ArtifactDeployer component.
 125  
      * 
 126  
      * @component
 127  
      */
 128  
     private ArtifactDeployer deployer;
 129  
 
 130  
     /**
 131  
      * Eclipse installation dir. If not set, a value for this parameter will be asked on the command line.
 132  
      * 
 133  
      * @parameter expression="${eclipseDir}"
 134  
      */
 135  
     private File eclipseDir;
 136  
 
 137  
     /**
 138  
      * Input handler, needed for comand line handling.
 139  
      * 
 140  
      * @component
 141  
      */
 142  
     protected InputHandler inputHandler;
 143  
 
 144  
     /**
 145  
      * Specifies a remote repository to which generated artifacts should be deployed to. If this property is specified,
 146  
      * artifacts are also deployed to the remote repo. The format for this parameter is <code>id::layout::url</code>
 147  
      * 
 148  
      * @parameter expression="${deployTo}"
 149  
      */
 150  
     private String deployTo;
 151  
 
 152  
     /**
 153  
      * @see org.apache.maven.plugin.Mojo#execute()
 154  
      */
 155  
     public void execute()
 156  
         throws MojoExecutionException, MojoFailureException
 157  
     {
 158  
         if ( eclipseDir == null )
 159  
         {
 160  
             getLog().info( "Eclipse directory? " );
 161  
 
 162  
             String eclipseDirString;
 163  
             try
 164  
             {
 165  
                 eclipseDirString = inputHandler.readLine();
 166  
             }
 167  
             catch ( IOException e )
 168  
             {
 169  
                 throw new MojoFailureException( "Unable to read from standard input" );
 170  
             }
 171  
             eclipseDir = new File( eclipseDirString );
 172  
         }
 173  
 
 174  
         if ( !eclipseDir.isDirectory() )
 175  
         {
 176  
             throw new MojoFailureException( "Directory " + eclipseDir.getAbsolutePath() + " doesn't exists" );
 177  
         }
 178  
 
 179  
         File pluginDir = new File( eclipseDir, "plugins" );
 180  
 
 181  
         if ( !pluginDir.isDirectory() )
 182  
         {
 183  
             throw new MojoFailureException( "Plugin directory " + pluginDir.getAbsolutePath() + " doesn't exists" );
 184  
         }
 185  
 
 186  
         File[] files = pluginDir.listFiles();
 187  
 
 188  
         ArtifactRepository remoteRepo = resolveRemoteRepo();
 189  
 
 190  
         if ( remoteRepo != null )
 191  
         {
 192  
             getLog().info( "Will deploy artifacts to remote repository " + deployTo );
 193  
         }
 194  
 
 195  
         Map plugins = new HashMap();
 196  
         Map models = new HashMap();
 197  
 
 198  
         for ( int j = 0; j < files.length; j++ )
 199  
         {
 200  
             File file = files[j];
 201  
 
 202  
             getLog().info( "Processing file " + file.getAbsolutePath() );
 203  
             
 204  
             processFile(file, plugins, models);
 205  
         }
 206  
 
 207  
         int i = 1;
 208  
         for ( Iterator it = plugins.keySet().iterator(); it.hasNext(); )
 209  
         {
 210  
             getLog().info( "Processing " + ( i++ ) + " of " + plugins.keySet().size() );
 211  
             String key = (String) it.next();
 212  
             EclipseOsgiPlugin plugin = (EclipseOsgiPlugin) plugins.get( key );
 213  
             Model model = (Model) models.get( key );
 214  
             writeArtifact( plugin, model, remoteRepo );
 215  
         }
 216  
     }
 217  
 
 218  
     protected void processFile( File file, Map plugins, Map models )
 219  
         throws MojoExecutionException, MojoFailureException
 220  
     {
 221  
         EclipseOsgiPlugin plugin = getEclipsePlugin( file );
 222  
 
 223  
         if ( plugin == null )
 224  
         {
 225  
             getLog().warn( "Skipping file " + file.getAbsolutePath() );
 226  
             return;
 227  
         }
 228  
 
 229  
         Model model = createModel( plugin );
 230  
 
 231  
         if ( model == null )
 232  
         {
 233  
             return;
 234  
         }
 235  
 
 236  
         processPlugin( plugin, model, plugins, models );
 237  
     }
 238  
 
 239  
     protected void processPlugin( EclipseOsgiPlugin plugin, Model model, Map plugins, Map models )
 240  
         throws MojoExecutionException, MojoFailureException
 241  
     {
 242  
         plugins.put( getKey( model ), plugin );
 243  
         models.put( getKey( model ), model );
 244  
     }
 245  
 
 246  
     protected String getKey( Model model )
 247  
     {
 248  
         return model.getGroupId() + "." + model.getArtifactId();
 249  
     }
 250  
 
 251  
     private String getKey(Dependency dependency)
 252  
     {
 253  
         return dependency.getGroupId() + "." + dependency.getArtifactId();
 254  
     }
 255  
 
 256  
     /**
 257  
      * Resolve version ranges in the model provided, overriding version ranges with versions from the dependency in the
 258  
      * provided map of models. TODO doesn't check if the version is in range, it just overwrites it
 259  
      * 
 260  
      * @param model
 261  
      * @param models
 262  
      * @throws MojoFailureException
 263  
      */
 264  
     protected void resolveVersionRanges( Model model, Map models )
 265  
         throws MojoFailureException
 266  
     {
 267  
         for ( Iterator it = model.getDependencies().iterator(); it.hasNext(); )
 268  
         {
 269  
             Dependency dep = (Dependency) it.next();
 270  
             if ( dep.getVersion().indexOf( "[" ) > -1 || dep.getVersion().indexOf( "(" ) > -1 )
 271  
             {
 272  
                 String key = getKey( model );
 273  
                 Model dependencyModel = (Model) models.get( getKey( dep ) );
 274  
                 if ( dependencyModel != null )
 275  
                 {
 276  
                     dep.setVersion( dependencyModel.getVersion() );
 277  
                 }
 278  
                 else
 279  
                 {
 280  
                     throw new MojoFailureException( "Unable to resolve version range for dependency " + dep +
 281  
                         " in project " + key );
 282  
                 }
 283  
             }
 284  
         }
 285  
     }
 286  
 
 287  
     /**
 288  
      * Get a {@link EclipseOsgiPlugin} object from a plugin jar/dir found in the target dir.
 289  
      * 
 290  
      * @param file plugin jar or dir
 291  
      * @throws MojoExecutionException if anything bad happens while parsing files
 292  
      */
 293  
     private EclipseOsgiPlugin getEclipsePlugin( File file )
 294  
         throws MojoExecutionException
 295  
     {
 296  
         if ( file.isDirectory() )
 297  
         {
 298  
             return new ExplodedPlugin( file );
 299  
         }
 300  
         else if ( file.getName().endsWith( ".jar" ) )
 301  
         {
 302  
             try
 303  
             {
 304  
                 return new PackagedPlugin( file );
 305  
             }
 306  
             catch ( IOException e )
 307  
             {
 308  
                 throw new MojoExecutionException( "Unable to access jar " + file.getAbsolutePath(), e );
 309  
             }
 310  
         }
 311  
 
 312  
         return null;
 313  
     }
 314  
 
 315  
     /**
 316  
      * Create the {@link Model} from a plugin manifest
 317  
      * 
 318  
      * @param plugin Eclipse plugin jar or dir
 319  
      * @throws MojoExecutionException if anything bad happens while parsing files
 320  
      */
 321  
     private Model createModel( EclipseOsgiPlugin plugin )
 322  
         throws MojoExecutionException
 323  
     {
 324  
 
 325  
         String name, bundleName, version, groupId, artifactId, requireBundle;
 326  
 
 327  
         try
 328  
         {
 329  
             if ( !plugin.hasManifest() )
 330  
             {
 331  
                 getLog().warn( "Plugin " + plugin + " does not have a manifest; skipping.." );
 332  
                 return null;
 333  
             }
 334  
 
 335  
             Analyzer analyzer = new Analyzer();
 336  
 
 337  
             Map bundleSymbolicNameHeader =
 338  
                 analyzer.parseHeader( plugin.getManifestAttribute( Analyzer.BUNDLE_SYMBOLICNAME ) );
 339  
             bundleName = (String) bundleSymbolicNameHeader.keySet().iterator().next();
 340  
             version = plugin.getManifestAttribute( Analyzer.BUNDLE_VERSION );
 341  
 
 342  
             if ( bundleName == null || version == null )
 343  
             {
 344  
                 getLog().error( "Unable to read bundle name/version from manifest, skipping..." );
 345  
                 return null;
 346  
             }
 347  
 
 348  
             version = osgiVersionToMavenVersion( version );
 349  
 
 350  
             name = plugin.getManifestAttribute( Analyzer.BUNDLE_NAME );
 351  
 
 352  
             requireBundle = plugin.getManifestAttribute( Analyzer.REQUIRE_BUNDLE );
 353  
 
 354  
         }
 355  
         catch ( IOException e )
 356  
         {
 357  
             throw new MojoExecutionException( "Error processing plugin " + plugin, e );
 358  
         }
 359  
 
 360  
         Dependency[] deps = parseDependencies( requireBundle );
 361  
 
 362  
         groupId = createGroupId( bundleName );
 363  
         artifactId = createArtifactId( bundleName );
 364  
 
 365  
         Model model = new Model();
 366  
         model.setModelVersion( "4.0.0" );
 367  
         model.setGroupId( groupId );
 368  
         model.setArtifactId( artifactId );
 369  
         model.setName( name );
 370  
         model.setVersion( version );
 371  
 
 372  
         model.setProperties( plugin.getPomProperties() );
 373  
 
 374  
         if ( groupId.startsWith( "org.eclipse" ) )
 375  
         {
 376  
             // why do we need a parent?
 377  
 
 378  
             // Parent parent = new Parent();
 379  
             // parent.setGroupId( "org.eclipse" );
 380  
             // parent.setArtifactId( "eclipse" );
 381  
             // parent.setVersion( "1" );
 382  
             // model.setParent( parent );
 383  
 
 384  
             // infer license for know projects, everything at eclipse is licensed under EPL
 385  
             // maybe too simplicistic, but better than nothing
 386  
             License license = new License();
 387  
             license.setName( "Eclipse Public License - v 1.0" );
 388  
             license.setUrl( "http://www.eclipse.org/org/documents/epl-v10.html" );
 389  
             model.addLicense( license );
 390  
         }
 391  
 
 392  
         if ( deps.length > 0 )
 393  
         {
 394  
             for ( int k = 0; k < deps.length; k++ )
 395  
             {
 396  
                 model.getDependencies().add( deps[k] );
 397  
             }
 398  
 
 399  
         }
 400  
 
 401  
         return model;
 402  
     }
 403  
     
 404  
     /**
 405  
      * Writes the artifact to the repo
 406  
      * 
 407  
      * @param model
 408  
      * @param remoteRepo remote repository (if set)
 409  
      * @throws MojoExecutionException
 410  
      */
 411  
     private void writeArtifact( EclipseOsgiPlugin plugin, Model model, ArtifactRepository remoteRepo )
 412  
         throws MojoExecutionException
 413  
     {
 414  
         Writer fw = null;
 415  
         ArtifactMetadata metadata = null;
 416  
         File pomFile = null;
 417  
         Artifact pomArtifact =
 418  
             artifactFactory.createArtifact( model.getGroupId(), model.getArtifactId(), model.getVersion(), null, "pom" );
 419  
         Artifact artifact =
 420  
             artifactFactory.createArtifact( model.getGroupId(), model.getArtifactId(), model.getVersion(), null,
 421  
                                             Constants.PROJECT_PACKAGING_JAR );
 422  
         try
 423  
         {
 424  
             pomFile = File.createTempFile( "pom-", ".xml" );
 425  
 
 426  
             // TODO use WriterFactory.newXmlWriter() when plexus-utils is upgraded to 1.4.5+
 427  
             fw = new OutputStreamWriter( new FileOutputStream( pomFile ), "UTF-8" );
 428  
             model.setModelEncoding( "UTF-8" ); // to be removed when encoding is detected instead of forced to UTF-8
 429  
             pomFile.deleteOnExit();
 430  
             new MavenXpp3Writer().write( fw, model );
 431  
             metadata = new ProjectArtifactMetadata( pomArtifact, pomFile );
 432  
             pomArtifact.addMetadata( metadata );
 433  
         }
 434  
         catch ( IOException e )
 435  
         {
 436  
             throw new MojoExecutionException( "Error writing temporary pom file: " + e.getMessage(), e );
 437  
         }
 438  
         finally
 439  
         {
 440  
             IOUtil.close( fw );
 441  
         }
 442  
 
 443  
         try
 444  
         {
 445  
             File jarFile = plugin.getJarFile();
 446  
 
 447  
             if ( remoteRepo != null )
 448  
             {
 449  
                 deployer.deploy( pomFile, pomArtifact, remoteRepo, localRepository );
 450  
                 deployer.deploy( jarFile, artifact, remoteRepo, localRepository );
 451  
             }
 452  
             else
 453  
             {
 454  
                 installer.install( pomFile, pomArtifact, localRepository );
 455  
                 installer.install( jarFile, artifact, localRepository );
 456  
             }
 457  
         }
 458  
         catch ( ArtifactDeploymentException e )
 459  
         {
 460  
             throw new MojoExecutionException( "Unable to deploy artifact to repository.", e );
 461  
         }
 462  
         catch ( ArtifactInstallationException e )
 463  
         {
 464  
             throw new MojoExecutionException( "Unable to install artifact to repository.", e );
 465  
         }
 466  
         catch ( IOException e )
 467  
         {
 468  
             throw new MojoExecutionException( "Error getting the jar file for plugin " + plugin, e );
 469  
         }
 470  
         finally
 471  
         {
 472  
             pomFile.delete();
 473  
         }
 474  
 
 475  
     }
 476  
 
 477  
     protected String osgiVersionToMavenVersion( String version )
 478  
     {
 479  
         return osgiVersionToMavenVersion( version, null, false );
 480  
     }
 481  
 
 482  
     /**
 483  
      * The 4th (build) token MUST be separed with "-" and not with "." in maven. A version with 4 dots is not parsed,
 484  
      * and the whole string is considered a qualifier. See tests in DefaultArtifactVersion for reference.
 485  
      * 
 486  
      * @param version initial version
 487  
      * @param forcedQualifier build number
 488  
      * @param stripQualifier always remove 4th token in version
 489  
      * @return converted version
 490  
      */
 491  
     protected String osgiVersionToMavenVersion( String version, String forcedQualifier, boolean stripQualifier )
 492  
     {
 493  16
         if ( stripQualifier && StringUtils.countMatches( version, "." ) > 2 )
 494  
         {
 495  4
             version = StringUtils.substring( version, 0, version.lastIndexOf( "." ) );
 496  
         }
 497  12
         else if ( StringUtils.countMatches( version, "." ) > 2 )
 498  
         {
 499  4
             int lastDot = version.lastIndexOf( "." );
 500  4
             if ( StringUtils.isNotEmpty( forcedQualifier ) )
 501  
             {
 502  2
                 version = StringUtils.substring( version, 0, lastDot ) + "-" + forcedQualifier;
 503  
             }
 504  
             else
 505  
             {
 506  2
                 version =
 507  
                     StringUtils.substring( version, 0, lastDot ) + "-" +
 508  
                         StringUtils.substring( version, lastDot + 1, version.length() );
 509  
             }
 510  
         }
 511  16
         return version;
 512  
     }
 513  
 
 514  
     /**
 515  
      * Resolves the deploy<code>deployTo</code> parameter to an <code>ArtifactRepository</code> instance (if set).
 516  
      * 
 517  
      * @throws MojoFailureException
 518  
      * @throws MojoExecutionException
 519  
      * @return ArtifactRepository instance of null if <code>deployTo</code> is not set.
 520  
      */
 521  
     private ArtifactRepository resolveRemoteRepo()
 522  
         throws MojoFailureException, MojoExecutionException
 523  
     {
 524  
         if ( deployTo != null )
 525  
         {
 526  
             Matcher matcher = DEPLOYTO_PATTERN.matcher( deployTo );
 527  
 
 528  
             if ( !matcher.matches() )
 529  
             {
 530  
                 throw new MojoFailureException( deployTo, "Invalid syntax for repository.",
 531  
                                                 "Invalid syntax for remote repository. Use \"id::layout::url\"." );
 532  
             }
 533  
             else
 534  
             {
 535  
                 String id = matcher.group( 1 ).trim();
 536  
                 String layout = matcher.group( 2 ).trim();
 537  
                 String url = matcher.group( 3 ).trim();
 538  
 
 539  
                 ArtifactRepositoryLayout repoLayout;
 540  
                 try
 541  
                 {
 542  
                     repoLayout = (ArtifactRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE, layout );
 543  
                 }
 544  
                 catch ( ComponentLookupException e )
 545  
                 {
 546  
                     throw new MojoExecutionException( "Cannot find repository layout: " + layout, e );
 547  
                 }
 548  
 
 549  
                 return new DefaultArtifactRepository( id, url, repoLayout );
 550  
             }
 551  
         }
 552  
         return null;
 553  
     }
 554  
 
 555  
     /**
 556  
      * {@inheritDoc}
 557  
      */
 558  
     public void contextualize( Context context )
 559  
         throws ContextException
 560  
     {
 561  
         this.container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
 562  
     }
 563  
 
 564  
     /**
 565  
      * Get the group id as the tokens until last dot e.g. <code>org.eclipse.jdt</code> -> <code>org.eclipse</code>
 566  
      * 
 567  
      * @param bundleName bundle name
 568  
      * @return group id
 569  
      */
 570  
     protected String createGroupId( String bundleName )
 571  
     {
 572  13
         int i = bundleName.lastIndexOf( "." );
 573  13
         if ( i > 0 )
 574  
         {
 575  12
             return bundleName.substring( 0, i );
 576  
         }
 577  
         else
 578  1
             return bundleName;
 579  
     }
 580  
 
 581  
     /**
 582  
      * Get the artifact id as the tokens after last dot e.g. <code>org.eclipse.jdt</code> -> <code>jdt</code>
 583  
      * 
 584  
      * @param bundleName bundle name
 585  
      * @return artifact id
 586  
      */
 587  
     protected String createArtifactId( String bundleName )
 588  
     {
 589  13
         int i = bundleName.lastIndexOf( "." );
 590  13
         if ( i > 0 )
 591  
         {
 592  12
             return bundleName.substring( i + 1 );
 593  
         }
 594  
         else
 595  1
             return bundleName;
 596  
     }
 597  
 
 598  
     /**
 599  
      * Parses the "Require-Bundle" and convert it to a list of dependencies.
 600  
      * 
 601  
      * @param requireBundle "Require-Bundle" entry
 602  
      * @return an array of <code>Dependency</code>
 603  
      */
 604  
     protected Dependency[] parseDependencies( String requireBundle )
 605  
     {
 606  4
         if ( requireBundle == null )
 607  
         {
 608  
             return new Dependency[0];
 609  
         }
 610  
 
 611  4
         List dependencies = new ArrayList();
 612  
 
 613  4
         Analyzer analyzer = new Analyzer();
 614  
 
 615  4
         Map requireBundleHeader = analyzer.parseHeader( requireBundle );
 616  
 
 617  
         // now iterates on bundles and extract dependencies
 618  4
         for ( Iterator iter = requireBundleHeader.entrySet().iterator(); iter.hasNext(); )
 619  
         {
 620  16
             Map.Entry entry = (Map.Entry) iter.next();
 621  16
             String bundleName = (String) entry.getKey();
 622  16
             Map attributes = (Map) entry.getValue();
 623  
 
 624  16
             String version = (String) attributes.get( Analyzer.BUNDLE_VERSION.toLowerCase() );
 625  16
             boolean optional = "optional".equals( attributes.get( "resolution:" ) );
 626  
 
 627  16
             if ( version == null )
 628  
             {
 629  
                 getLog().info( "Missing version for bundle " + bundleName + ", assuming any version > 0" );
 630  
                 version = "[0,)";
 631  
             }
 632  
 
 633  16
             version = fixBuildNumberSeparator( version );
 634  
 
 635  16
             Dependency dep = new Dependency();
 636  16
             dep.setGroupId( createGroupId( bundleName ) );
 637  16
             dep.setArtifactId( createArtifactId( bundleName ) );
 638  16
             dep.setVersion( version );
 639  16
             dep.setOptional( optional );
 640  
 
 641  16
             dependencies.add( dep );
 642  
 
 643  16
         }
 644  
 
 645  4
         return (Dependency[]) dependencies.toArray( new Dependency[dependencies.size()] );
 646  
 
 647  
     }
 648  
 
 649  
     /**
 650  
      * Fix the separator for the 4th token in a versions. In maven this must be "-", in OSGI it's "."
 651  
      * 
 652  
      * @param versionRange input range
 653  
      * @return modified version range
 654  
      */
 655  
     protected String fixBuildNumberSeparator( String versionRange )
 656  
     {
 657  
         // should not be called with a null versionRange, but a check doesn't hurt...
 658  16
         if ( versionRange == null )
 659  
         {
 660  
             return null;
 661  
         }
 662  
 
 663  16
         StringBuffer newVersionRange = new StringBuffer();
 664  
 
 665  16
         Matcher matcher = VERSION_PATTERN.matcher( versionRange );
 666  
 
 667  48
         while ( matcher.find() )
 668  
         {
 669  32
             String group = matcher.group();
 670  
 
 671  32
             if ( StringUtils.countMatches( group, "." ) > 2 )
 672  
             {
 673  
                 // build number found, fix it
 674  16
                 int lastDot = group.lastIndexOf( "." );
 675  16
                 group =
 676  
                     StringUtils.substring( group, 0, lastDot ) + "-" +
 677  
                         StringUtils.substring( group, lastDot + 1, group.length() );
 678  
             }
 679  32
             matcher.appendReplacement( newVersionRange, group );
 680  32
         }
 681  
 
 682  16
         matcher.appendTail( newVersionRange );
 683  
 
 684  16
         return newVersionRange.toString();
 685  
     }
 686  
 
 687  
 }