1 package org.apache.maven.plugins.assembly.utils;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.ListIterator;
27 import java.util.Properties;
28
29 import javax.annotation.Nonnull;
30 import javax.annotation.Nullable;
31
32 import org.apache.maven.artifact.Artifact;
33 import org.apache.maven.execution.MavenSession;
34 import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
35 import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
36 import org.apache.maven.plugins.assembly.model.Assembly;
37 import org.apache.maven.project.MavenProject;
38 import org.apache.maven.shared.utils.Os;
39 import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator;
40 import org.codehaus.plexus.interpolation.fixed.MapBasedValueSource;
41 import org.codehaus.plexus.interpolation.fixed.PrefixedObjectValueSource;
42 import org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource;
43 import org.codehaus.plexus.interpolation.fixed.PropertiesBasedValueSource;
44 import org.codehaus.plexus.logging.Logger;
45 import org.codehaus.plexus.util.StringUtils;
46
47
48
49
50 public final class AssemblyFormatUtils
51 {
52
53 private AssemblyFormatUtils()
54 {
55 }
56
57
58
59
60
61
62
63 public static String getDistributionName( final Assembly assembly, final AssemblerConfigurationSource configSource )
64 {
65 final String finalName = configSource.getFinalName();
66 final boolean appendAssemblyId = configSource.isAssemblyIdAppended();
67
68 String distributionName = finalName;
69 if ( appendAssemblyId )
70 {
71 distributionName = finalName + "-" + assembly.getId();
72 }
73
74 return distributionName;
75 }
76
77
78 @Nonnull
79 public static FixedStringSearchInterpolator finalNameInterpolator( String finalName )
80 {
81 final Properties specialExpressionOverrides = new Properties();
82
83 if ( finalName != null )
84 {
85 specialExpressionOverrides.setProperty( "finalName", finalName );
86 specialExpressionOverrides.setProperty( "build.finalName", finalName );
87 }
88 else
89 {
90 return FixedStringSearchInterpolator.empty();
91 }
92
93 return FixedStringSearchInterpolator.create( new PropertiesBasedValueSource( specialExpressionOverrides ) );
94 }
95
96 @Nonnull
97 public static FixedStringSearchInterpolator moduleProjectInterpolator( final MavenProject moduleProject )
98 {
99 if ( moduleProject != null )
100 {
101 return FixedStringSearchInterpolator.createWithPermittedNulls(
102 new PrefixedObjectValueSource( "module.", moduleProject ),
103 new PrefixedPropertiesValueSource( "module.properties.", moduleProject.getProperties() ),
104 moduleProject.getArtifact() != null
105 ? new PrefixedObjectValueSource( "module.", moduleProject.getArtifact() )
106 : null );
107 }
108 else
109 {
110 return FixedStringSearchInterpolator.empty();
111 }
112
113 }
114
115 public static FixedStringSearchInterpolator moduleArtifactInterpolator( Artifact moduleArtifact )
116 {
117 if ( moduleArtifact != null )
118 {
119 final String groupIdPath = moduleArtifact.getGroupId().replace( '.', '/' );
120
121 return FixedStringSearchInterpolator.create(
122 new MapBasedValueSource( Collections.singletonMap( "module.groupIdPath", groupIdPath ) ),
123 new PrefixedObjectValueSource( "module.", moduleArtifact ),
124 new PrefixedObjectValueSource( "module.", moduleArtifact.getArtifactHandler() ),
125 new PrefixedObjectValueSource( "module.handler.", moduleArtifact.getArtifactHandler() ) );
126 }
127 else
128 {
129 return FixedStringSearchInterpolator.empty();
130 }
131
132 }
133
134 @Nonnull
135 public static FixedStringSearchInterpolator artifactProjectInterpolator( final MavenProject artifactProject )
136 {
137 if ( artifactProject != null )
138 {
139 PrefixedObjectValueSource vs = null;
140 if ( artifactProject.getArtifact() != null )
141 {
142 vs = new PrefixedObjectValueSource( "artifact.", artifactProject.getArtifact() );
143 }
144
145 final String groupIdPath = artifactProject.getGroupId().replace( '.', '/' );
146
147 return FixedStringSearchInterpolator.createWithPermittedNulls(
148 new MapBasedValueSource( Collections.singletonMap( "artifact.groupIdPath", groupIdPath ) ),
149 new PrefixedObjectValueSource( "artifact.", artifactProject ),
150 new PrefixedPropertiesValueSource( "artifact.properties.", artifactProject.getProperties() ), vs );
151 }
152 else
153 {
154 return FixedStringSearchInterpolator.empty();
155 }
156 }
157
158 @Nonnull
159 public static FixedStringSearchInterpolator artifactInterpolator( @Nonnull final Artifact artifact )
160 {
161 final String groupIdPath = artifact.getGroupId().replace( '.', '/' );
162
163 return FixedStringSearchInterpolator.create(
164 new MapBasedValueSource( Collections.singletonMap( "artifact.groupIdPath", groupIdPath ) ),
165 new PrefixedObjectValueSource( "artifact.", artifact ),
166 new PrefixedObjectValueSource( "artifact.", artifact.getArtifactHandler() ),
167 new PrefixedObjectValueSource( "artifact.handler.", artifact.getArtifactHandler() ) );
168 }
169
170
171 @Nonnull
172 public static FixedStringSearchInterpolator classifierRules( final Artifact artifact )
173 {
174 final Properties specialRules = new Properties();
175
176 final String classifier = ProjectUtils.getClassifier( artifact );
177 if ( classifier != null )
178 {
179 specialRules.setProperty( "dashClassifier?", "-" + classifier );
180 specialRules.setProperty( "dashClassifier", "-" + classifier );
181 }
182 else
183 {
184 specialRules.setProperty( "dashClassifier?", "" );
185 specialRules.setProperty( "dashClassifier", "" );
186 }
187
188 return FixedStringSearchInterpolator.create( new PropertiesBasedValueSource( specialRules ) );
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 public static String getOutputDirectory( final String output, final MavenProject artifactProject,
219 final String finalName, final AssemblerConfigurationSource configSource )
220 throws AssemblyFormattingException
221 {
222 return getOutputDirectory( output, finalName, configSource, moduleProjectInterpolator( null ),
223 artifactProjectInterpolator( artifactProject ) );
224 }
225
226
227 private static FixedStringSearchInterpolator executionPropertiesInterpolator(
228 AssemblerConfigurationSource configSource )
229 {
230 MavenSession session;
231
232 if ( configSource != null )
233 {
234 session = configSource.getMavenSession();
235
236 if ( session != null )
237 {
238 Properties userProperties = session.getExecutionProperties();
239
240 if ( userProperties != null )
241 {
242 return FixedStringSearchInterpolator.create( new PropertiesBasedValueSource( userProperties ) );
243 }
244 }
245 }
246 return FixedStringSearchInterpolator.empty();
247 }
248
249 private static FixedStringSearchInterpolator mainProjectOnlyInterpolator( MavenProject mainProject )
250 {
251 if ( mainProject != null )
252 {
253
254 return FixedStringSearchInterpolator.create(
255 new org.codehaus.plexus.interpolation.fixed.PrefixedObjectValueSource(
256 InterpolationConstants.PROJECT_PREFIXES, mainProject, true ) );
257 }
258 else
259 {
260 return FixedStringSearchInterpolator.empty();
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 @Nonnull
302 public static String fixRelativeRefs( @Nonnull String src )
303 {
304 String value = src;
305
306 String[] separators = { "/", "\\" };
307
308 String finalSep = null;
309 for ( String sep : separators )
310 {
311 if ( value.endsWith( sep ) )
312 {
313 finalSep = sep;
314 }
315
316 if ( value.contains( "." + sep ) )
317 {
318 List<String> parts = new ArrayList<>();
319 parts.addAll( Arrays.asList( value.split( sep.replace( "\\", "\\\\" ) ) ) );
320
321 for ( ListIterator<String> it = parts.listIterator(); it.hasNext(); )
322 {
323 String part = it.next();
324 if ( ".".equals( part ) )
325 {
326 it.remove();
327 }
328 else if ( "..".equals( part ) )
329 {
330 it.remove();
331 if ( it.hasPrevious() )
332 {
333 it.previous();
334 it.remove();
335 }
336 }
337 }
338
339 value = StringUtils.join( parts.iterator(), sep );
340 }
341 }
342
343 if ( finalSep != null && value.length() > 0 && !value.endsWith( finalSep ) )
344 {
345 value += finalSep;
346 }
347
348 return value;
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386 public static String evaluateFileNameMapping( final String expression, @Nonnull final Artifact artifact,
387 @Nullable final MavenProject mainProject,
388 @Nullable final Artifact moduleArtifact,
389 @Nonnull final AssemblerConfigurationSource configSource,
390 FixedStringSearchInterpolator moduleProjectInterpolator,
391 FixedStringSearchInterpolator artifactProjectInterpolator )
392 throws AssemblyFormattingException
393 {
394 String value = expression;
395
396 final FixedStringSearchInterpolator interpolator =
397 FixedStringSearchInterpolator.create( moduleArtifactInterpolator( moduleArtifact ),
398 moduleProjectInterpolator, artifactInterpolator( artifact ),
399 artifactProjectInterpolator,
400 mainProjectOnlyInterpolator( mainProject ),
401 classifierRules( artifact ),
402 executionPropertiesInterpolator( configSource ),
403 configSource.getMainProjectInterpolator(),
404 configSource.getCommandLinePropsInterpolator(),
405 configSource.getEnvInterpolator() );
406
407 value = interpolator.interpolate( value );
408
409 value = StringUtils.replace( value, "//", "/" );
410 value = StringUtils.replace( value, "\\\\", "\\" );
411 value = fixRelativeRefs( value );
412
413 return value;
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442 public static String getOutputDirectory( final String output, final String finalName,
443 final AssemblerConfigurationSource configSource,
444 FixedStringSearchInterpolator moduleProjectIntrpolator,
445 FixedStringSearchInterpolator artifactProjectInterpolator )
446 throws AssemblyFormattingException
447 {
448 String value = output;
449 if ( value == null )
450 {
451 value = "";
452 }
453
454 final FixedStringSearchInterpolator interpolator =
455 FixedStringSearchInterpolator.create( finalNameInterpolator( finalName ), moduleProjectIntrpolator,
456 artifactProjectInterpolator,
457 executionPropertiesInterpolator( configSource ),
458 configSource.getMainProjectInterpolator(),
459 configSource.getCommandLinePropsInterpolator(),
460 configSource.getEnvInterpolator() );
461
462 value = interpolator.interpolate( value );
463
464 if ( ( value.length() > 0 ) && !value.endsWith( "/" ) && !value.endsWith( "\\" ) )
465 {
466 value += "/";
467 }
468
469 if ( ( value.length() > 0 ) && ( value.startsWith( "/" ) || value.startsWith( "\\" ) ) )
470 {
471 value = value.substring( 1 );
472 }
473
474 value = StringUtils.replace( value, "//", "/" );
475 value = StringUtils.replace( value, "\\\\", "\\" );
476 value = fixRelativeRefs( value );
477
478 return value;
479 }
480
481 public static void warnForPlatformSpecifics( Logger logger, String destDirectory )
482 {
483 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
484 {
485 if ( isUnixRootReference( destDirectory ) )
486 {
487 logger.error( "OS=Windows and the assembly descriptor contains a *nix-specific root-relative reference"
488 + " (starting with slash): " + destDirectory );
489 }
490 else if ( isWindowsPath( destDirectory ) )
491 {
492 logger.warn( "The assembly descriptor contains a Windows-specific directory reference"
493 + " (with a drive letter). This is not portable and will fail on non-Windows: "
494 + destDirectory );
495 }
496 }
497 else
498 {
499 if ( isWindowsPath( destDirectory ) )
500 {
501 logger.error(
502 "OS=Non-Windows and the assembly descriptor contains a Windows-specific directory reference"
503 + " (with a drive letter): " + destDirectory );
504 }
505 else if ( isUnixRootReference( destDirectory ) )
506 {
507 logger.warn( "The assembly descriptor contains a *nix-specific root-relative reference"
508 + " (starting with slash). This is not portable and might fail on Windows: "
509 + destDirectory );
510 }
511 }
512 }
513
514 static boolean isWindowsPath( String destDirectory )
515 {
516 return ( destDirectory != null && destDirectory.length() >= 2 && destDirectory.charAt( 1 ) == ':' );
517 }
518
519 static boolean isUnixRootReference( String destDirectory )
520 {
521 return ( destDirectory != null && destDirectory.startsWith( "/" ) );
522 }
523
524
525 }