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