1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.deployer.ArtifactDeployer;
36 import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
37 import org.apache.maven.artifact.factory.ArtifactFactory;
38 import org.apache.maven.artifact.installer.ArtifactInstallationException;
39 import org.apache.maven.artifact.installer.ArtifactInstaller;
40 import org.apache.maven.artifact.metadata.ArtifactMetadata;
41 import org.apache.maven.artifact.repository.ArtifactRepository;
42 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
43 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
44 import org.apache.maven.model.Dependency;
45 import org.apache.maven.model.License;
46 import org.apache.maven.model.Model;
47 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
48 import org.apache.maven.plugin.AbstractMojo;
49 import org.apache.maven.plugin.MojoExecutionException;
50 import org.apache.maven.plugin.MojoFailureException;
51 import org.apache.maven.plugin.eclipse.osgiplugin.EclipseOsgiPlugin;
52 import org.apache.maven.plugin.eclipse.osgiplugin.ExplodedPlugin;
53 import org.apache.maven.plugin.eclipse.osgiplugin.PackagedPlugin;
54 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
55 import org.codehaus.plexus.PlexusConstants;
56 import org.codehaus.plexus.PlexusContainer;
57 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
58 import org.codehaus.plexus.components.interactivity.InputHandler;
59 import org.codehaus.plexus.context.Context;
60 import org.codehaus.plexus.context.ContextException;
61 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
62 import org.codehaus.plexus.util.IOUtil;
63 import org.codehaus.plexus.util.StringUtils;
64
65 import aQute.lib.osgi.Analyzer;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public class EclipseToMavenMojo
81 extends AbstractMojo
82 implements Contextualizable
83 {
84
85
86
87
88 private static final Pattern DEPLOYTO_PATTERN = Pattern.compile( "(.+)::(.+)::(.+)" );
89
90
91
92
93 private static final Pattern VERSION_PATTERN = Pattern.compile( "(([0-9]+\\.)+[0-9]+)" );
94
95
96
97
98 private PlexusContainer container;
99
100
101
102
103
104
105
106
107 private ArtifactRepository localRepository;
108
109
110
111
112
113
114 private ArtifactRepositoryFactory artifactRepositoryFactory;
115
116
117
118
119
120
121 private ArtifactFactory artifactFactory;
122
123
124
125
126
127
128 protected ArtifactInstaller installer;
129
130
131
132
133
134
135 private ArtifactDeployer deployer;
136
137
138
139
140
141
142 private File eclipseDir;
143
144
145
146
147
148
149 protected InputHandler inputHandler;
150
151
152
153
154
155
156
157
158
159
160 private boolean stripQualifier;
161
162
163
164
165
166
167
168 private String deployTo;
169
170
171
172
173 public void execute()
174 throws MojoExecutionException, MojoFailureException
175 {
176 if ( eclipseDir == null )
177 {
178 getLog().info( Messages.getString( "EclipseToMavenMojo.eclipseDirectoryPrompt" ) );
179
180 String eclipseDirString;
181 try
182 {
183 eclipseDirString = inputHandler.readLine();
184 }
185 catch ( IOException e )
186 {
187 throw new MojoFailureException( Messages.getString( "EclipseToMavenMojo.errorreadingfromstandardinput" ) );
188 }
189 eclipseDir = new File( eclipseDirString );
190 }
191
192 if ( !eclipseDir.isDirectory() )
193 {
194 throw new MojoFailureException(
195 Messages.getString(
196 "EclipseToMavenMojo.directoydoesnotexist", eclipseDir.getAbsolutePath() ) );
197 }
198
199 File pluginDir = new File( eclipseDir, "plugins" );
200
201 if ( !pluginDir.isDirectory() )
202 {
203 throw new MojoFailureException(
204 Messages.getString(
205 "EclipseToMavenMojo.plugindirectorydoesnotexist", pluginDir.getAbsolutePath() ) );
206 }
207
208 File[] files = pluginDir.listFiles();
209
210 ArtifactRepository remoteRepo = resolveRemoteRepo();
211
212 if ( remoteRepo != null )
213 {
214 getLog().info( Messages.getString( "EclipseToMavenMojo.remoterepositorydeployto", deployTo ) );
215 }
216
217 Map plugins = new HashMap();
218 Map models = new HashMap();
219
220 for ( int j = 0; j < files.length; j++ )
221 {
222 File file = files[j];
223
224 getLog().info( Messages.getString( "EclipseToMavenMojo.processingfile", file.getAbsolutePath() ) );
225
226 processFile( file, plugins, models );
227 }
228
229 int i = 1;
230 for ( Iterator it = plugins.keySet().iterator(); it.hasNext(); )
231 {
232 getLog().info(
233 Messages.getString(
234 "EclipseToMavenMojo.processingplugin", new Object[] { new Integer( i++ ), new Integer( plugins.keySet().size() ) } ) );
235 String key = (String) it.next();
236 EclipseOsgiPlugin plugin = (EclipseOsgiPlugin) plugins.get( key );
237 Model model = (Model) models.get( key );
238 writeArtifact( plugin, model, remoteRepo );
239 }
240 }
241
242 protected void processFile( File file, Map plugins, Map models )
243 throws MojoExecutionException, MojoFailureException
244 {
245 EclipseOsgiPlugin plugin = getEclipsePlugin( file );
246
247 if ( plugin == null )
248 {
249 getLog().warn( Messages.getString( "EclipseToMavenMojo.skippingfile", file.getAbsolutePath() ) );
250 return;
251 }
252
253 Model model = createModel( plugin );
254
255 if ( model == null )
256 {
257 return;
258 }
259
260 processPlugin( plugin, model, plugins, models );
261 }
262
263 protected void processPlugin( EclipseOsgiPlugin plugin, Model model, Map plugins, Map models )
264 throws MojoExecutionException, MojoFailureException
265 {
266 plugins.put( getKey( model ), plugin );
267 models.put( getKey( model ), model );
268 }
269
270 protected String getKey( Model model )
271 {
272 return model.getGroupId() + "." + model.getArtifactId();
273 }
274
275 private String getKey( Dependency dependency )
276 {
277 return dependency.getGroupId() + "." + dependency.getArtifactId();
278 }
279
280
281
282
283
284
285
286
287
288 protected void resolveVersionRanges( Model model, Map models )
289 throws MojoFailureException
290 {
291 for ( Iterator it = model.getDependencies().iterator(); it.hasNext(); )
292 {
293 Dependency dep = (Dependency) it.next();
294 if ( dep.getVersion().indexOf( "[" ) > -1 || dep.getVersion().indexOf( "(" ) > -1 )
295 {
296 String key = getKey( model );
297 Model dependencyModel = (Model) models.get( getKey( dep ) );
298 if ( dependencyModel != null )
299 {
300 dep.setVersion( dependencyModel.getVersion() );
301 }
302 else
303 {
304 throw new MojoFailureException(
305 Messages.getString(
306 "EclipseToMavenMojo.unabletoresolveversionrange", new Object[] { dep
307 , key } ) );
308 }
309 }
310 }
311 }
312
313
314
315
316
317
318
319 private EclipseOsgiPlugin getEclipsePlugin( File file )
320 throws MojoExecutionException
321 {
322 if ( file.isDirectory() )
323 {
324 return new ExplodedPlugin( file );
325 }
326 else if ( file.getName().endsWith( ".jar" ) )
327 {
328 try
329 {
330 return new PackagedPlugin( file );
331 }
332 catch ( IOException e )
333 {
334 throw new MojoExecutionException(
335 Messages.getString(
336 "EclipseToMavenMojo.unabletoaccessjar", file.getAbsolutePath() ), e );
337 }
338 }
339
340 return null;
341 }
342
343
344
345
346
347
348
349 private Model createModel( EclipseOsgiPlugin plugin )
350 throws MojoExecutionException
351 {
352
353 String name, bundleName, version, groupId, artifactId, requireBundle;
354
355 try
356 {
357 if ( !plugin.hasManifest() )
358 {
359 getLog().warn( Messages.getString( "EclipseToMavenMojo.plugindoesnothavemanifest", plugin ) );
360 return null;
361 }
362
363 Analyzer analyzer = new Analyzer();
364
365 Map bundleSymbolicNameHeader =
366 analyzer.parseHeader( plugin.getManifestAttribute( Analyzer.BUNDLE_SYMBOLICNAME ) );
367 bundleName = (String) bundleSymbolicNameHeader.keySet().iterator().next();
368 version = plugin.getManifestAttribute( Analyzer.BUNDLE_VERSION );
369
370 if ( bundleName == null || version == null )
371 {
372 getLog().error( Messages.getString( "EclipseToMavenMojo.unabletoreadbundlefrommanifest" ) );
373 return null;
374 }
375
376 version = osgiVersionToMavenVersion( version );
377
378 name = plugin.getManifestAttribute( Analyzer.BUNDLE_NAME );
379
380 requireBundle = plugin.getManifestAttribute( Analyzer.REQUIRE_BUNDLE );
381
382 }
383 catch ( IOException e )
384 {
385 throw new MojoExecutionException(
386 Messages.getString( "EclipseToMavenMojo.errorprocessingplugin", plugin ), e );
387 }
388
389 Dependency[] deps = parseDependencies( requireBundle );
390
391 groupId = createGroupId( bundleName );
392 artifactId = createArtifactId( bundleName );
393
394 Model model = new Model();
395 model.setModelVersion( "4.0.0" );
396 model.setGroupId( groupId );
397 model.setArtifactId( artifactId );
398 model.setName( name );
399 model.setVersion( version );
400
401 model.setProperties( plugin.getPomProperties() );
402
403 if ( groupId.startsWith( "org.eclipse" ) )
404 {
405
406
407
408
409
410
411
412
413
414
415 License license = new License();
416 license.setName( "Eclipse Public License - v 1.0" );
417 license.setUrl( "http://www.eclipse.org/org/documents/epl-v10.html" ); //$NON-NLS-1$
418 model.addLicense( license );
419 }
420
421 if ( deps.length > 0 )
422 {
423 for ( int k = 0; k < deps.length; k++ )
424 {
425 model.getDependencies().add( deps[k] );
426 }
427
428 }
429
430 return model;
431 }
432
433
434
435
436
437
438
439
440 private void writeArtifact( EclipseOsgiPlugin plugin, Model model, ArtifactRepository remoteRepo )
441 throws MojoExecutionException
442 {
443 Writer fw = null;
444 ArtifactMetadata metadata = null;
445 File pomFile = null;
446 Artifact pomArtifact =
447 artifactFactory.createArtifact( model.getGroupId(), model.getArtifactId(), model.getVersion(), null, "pom" );
448 Artifact artifact =
449 artifactFactory.createArtifact( model.getGroupId(), model.getArtifactId(), model.getVersion(), null,
450 Constants.PROJECT_PACKAGING_JAR );
451 try
452 {
453 pomFile = File.createTempFile( "pom-", ".xml" );
454
455
456 fw = new OutputStreamWriter( new FileOutputStream( pomFile ), "UTF-8" );
457 model.setModelEncoding( "UTF-8" );
458 pomFile.deleteOnExit();
459 new MavenXpp3Writer().write( fw, model );
460 metadata = new ProjectArtifactMetadata( pomArtifact, pomFile );
461 pomArtifact.addMetadata( metadata );
462 }
463 catch ( IOException e )
464 {
465 throw new MojoExecutionException(
466 Messages.getString(
467 "EclipseToMavenMojo.errorwritingtemporarypom", e.getMessage() ), e );
468 }
469 finally
470 {
471 IOUtil.close( fw );
472 }
473
474 try
475 {
476 File jarFile = plugin.getJarFile();
477
478 if ( remoteRepo != null )
479 {
480 deployer.deploy( pomFile, pomArtifact, remoteRepo, localRepository );
481 deployer.deploy( jarFile, artifact, remoteRepo, localRepository );
482 }
483 else
484 {
485 installer.install( pomFile, pomArtifact, localRepository );
486 installer.install( jarFile, artifact, localRepository );
487 }
488 }
489 catch ( ArtifactDeploymentException e )
490 {
491 throw new MojoExecutionException(
492 Messages.getString( "EclipseToMavenMojo.errordeployartifacttorepository" ), e );
493 }
494 catch ( ArtifactInstallationException e )
495 {
496 throw new MojoExecutionException(
497 Messages.getString( "EclipseToMavenMojo.errorinstallartifacttorepository" ), e );
498 }
499 catch ( IOException e )
500 {
501 throw new MojoExecutionException(
502 Messages.getString(
503 "EclipseToMavenMojo.errorgettingjarfileforplugin", plugin ), e );
504 }
505 finally
506 {
507 pomFile.delete();
508 }
509
510 }
511
512 protected String osgiVersionToMavenVersion( String version )
513 {
514 return osgiVersionToMavenVersion( version, null, stripQualifier );
515 }
516
517
518
519
520
521
522
523
524
525
526 protected String osgiVersionToMavenVersion( String version, String forcedQualifier, boolean stripQualifier )
527 {
528 if ( stripQualifier && StringUtils.countMatches( version, "." ) > 2 )
529 {
530 version = StringUtils.substring( version, 0, version.lastIndexOf( '.' ) );
531 }
532 else if ( StringUtils.countMatches( version, "." ) > 2 )
533 {
534 int lastDot = version.lastIndexOf( '.' );
535 if ( StringUtils.isNotEmpty( forcedQualifier ) )
536 {
537 version = StringUtils.substring( version, 0, lastDot ) + "-" + forcedQualifier;
538 }
539 else
540 {
541 version = StringUtils.substring( version, 0, lastDot ) + "-"
542 + StringUtils.substring( version, lastDot + 1, version.length() );
543 }
544 }
545 return version;
546 }
547
548
549
550
551
552
553
554
555 private ArtifactRepository resolveRemoteRepo()
556 throws MojoFailureException, MojoExecutionException
557 {
558 if ( deployTo != null )
559 {
560 Matcher matcher = DEPLOYTO_PATTERN.matcher( deployTo );
561
562 if ( !matcher.matches() )
563 {
564 throw new MojoFailureException( deployTo,
565 Messages.getString( "EclipseToMavenMojo.invalidsyntaxforrepository" ),
566 Messages.getString( "EclipseToMavenMojo.invalidremoterepositorysyntax" ) );
567 }
568 else
569 {
570 String id = matcher.group( 1 ).trim();
571 String layout = matcher.group( 2 ).trim();
572 String url = matcher.group( 3 ).trim();
573
574 ArtifactRepositoryLayout repoLayout;
575 try
576 {
577 repoLayout = (ArtifactRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE, layout );
578 }
579 catch ( ComponentLookupException e )
580 {
581 throw new MojoExecutionException(
582 Messages.getString(
583 "EclipseToMavenMojo.cannotfindrepositorylayout", layout ), e );
584 }
585
586 return artifactRepositoryFactory.createDeploymentArtifactRepository( id, url, repoLayout, true );
587 }
588 }
589 return null;
590 }
591
592
593
594
595 public void contextualize( Context context )
596 throws ContextException
597 {
598 this.container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
599 }
600
601
602
603
604
605
606
607 protected String createGroupId( String bundleName )
608 {
609 int i = bundleName.lastIndexOf( '.' );
610 if ( i > 0 )
611 {
612 return bundleName.substring( 0, i );
613 }
614 else
615 return bundleName;
616 }
617
618
619
620
621
622
623
624 protected String createArtifactId( String bundleName )
625 {
626 int i = bundleName.lastIndexOf( '.' );
627 if ( i > 0 )
628 {
629 return bundleName.substring( i + 1 );
630 }
631 else
632 return bundleName;
633 }
634
635
636
637
638
639
640
641 protected Dependency[] parseDependencies( String requireBundle )
642 {
643 if ( requireBundle == null )
644 {
645 return new Dependency[0];
646 }
647
648 List dependencies = new ArrayList();
649
650 Analyzer analyzer = new Analyzer();
651
652 Map requireBundleHeader = analyzer.parseHeader( requireBundle );
653
654
655 for ( Iterator iter = requireBundleHeader.entrySet().iterator(); iter.hasNext(); )
656 {
657 Map.Entry entry = (Map.Entry) iter.next();
658 String bundleName = (String) entry.getKey();
659 Map attributes = (Map) entry.getValue();
660
661 String version = (String) attributes.get( Analyzer.BUNDLE_VERSION.toLowerCase() );
662 boolean optional = "optional".equals( attributes.get( "resolution:" ) );
663
664 if ( version == null )
665 {
666 getLog().info( Messages.getString( "EclipseToMavenMojo.missingversionforbundle", bundleName ) );
667 version = "[0,)";
668 }
669
670 version = fixBuildNumberSeparator( version );
671
672 Dependency dep = new Dependency();
673 dep.setGroupId( createGroupId( bundleName ) );
674 dep.setArtifactId( createArtifactId( bundleName ) );
675 dep.setVersion( version );
676 dep.setOptional( optional );
677
678 dependencies.add( dep );
679
680 }
681
682 return (Dependency[]) dependencies.toArray( new Dependency[dependencies.size()] );
683
684 }
685
686
687
688
689
690
691
692 protected String fixBuildNumberSeparator( String versionRange )
693 {
694
695 if ( versionRange == null )
696 {
697 return null;
698 }
699
700 StringBuffer newVersionRange = new StringBuffer();
701
702 Matcher matcher = VERSION_PATTERN.matcher( versionRange );
703
704 while ( matcher.find() )
705 {
706 String group = matcher.group();
707
708 if ( StringUtils.countMatches( group, "." ) > 2 )
709 {
710
711 int lastDot = group.lastIndexOf( '.' );
712 group = StringUtils.substring( group, 0, lastDot ) + "-"
713 + StringUtils.substring( group, lastDot + 1, group.length() );
714 }
715 matcher.appendReplacement( newVersionRange, group );
716 }
717
718 matcher.appendTail( newVersionRange );
719
720 return newVersionRange.toString();
721 }
722
723 }