1 package org.apache.maven.plugin.war.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.model.Dependency;
24 import org.codehaus.plexus.util.StringUtils;
25
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34
35
36
37
38
39
40
41
42
43
44 public class WebappStructure
45 {
46
47 private Map<String, PathSet> registeredFiles;
48
49 private List<DependencyInfo> dependenciesInfo;
50
51 private transient PathSet allFiles = new PathSet();
52
53 private transient WebappStructure cache;
54
55
56
57
58
59
60 public WebappStructure( List<Dependency> dependencies )
61 {
62 this.dependenciesInfo = createDependenciesInfoList( dependencies );
63 this.registeredFiles = new HashMap<String, PathSet>();
64 this.cache = null;
65 }
66
67
68
69
70
71
72
73 public WebappStructure( List<Dependency> dependencies, WebappStructure cache )
74 {
75 this.dependenciesInfo = createDependenciesInfoList( dependencies );
76 this.registeredFiles = new HashMap<String, PathSet>();
77 if ( cache == null )
78 {
79 this.cache = new WebappStructure( dependencies );
80 }
81 else
82 {
83 this.cache = cache;
84 }
85 }
86
87
88
89
90
91
92 public List<DependencyInfo> getDependenciesInfo()
93 {
94 return dependenciesInfo;
95 }
96
97
98
99
100
101
102 public List<Dependency> getDependencies()
103 {
104 final List<Dependency> result = new ArrayList<Dependency>();
105 if ( dependenciesInfo == null )
106 {
107 return result;
108 }
109 for ( DependencyInfo dependencyInfo : dependenciesInfo )
110 {
111 result.add( dependencyInfo.getDependency() );
112 }
113 return result;
114 }
115
116
117
118
119
120
121
122 public boolean isRegistered( String path )
123 {
124 return getFullStructure().contains( path );
125
126 }
127
128
129
130
131
132
133
134
135
136 public boolean registerFile( String id, String path )
137 {
138 if ( !isRegistered( path ) )
139 {
140 doRegister( id, path );
141 return true;
142 }
143 else
144 {
145 return false;
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161 public boolean registerFileForced( String id, String path )
162 {
163 if ( !isRegistered( path ) )
164 {
165 doRegister( id, path );
166 return false;
167 }
168 else
169 {
170
171 getStructure( getOwner( path ) ).remove( path );
172 getStructure( id ).add( path );
173 return true;
174 }
175
176 }
177
178
179
180
181
182
183
184
185
186
187 public void registerFile( String id, String path, RegistrationCallback callback )
188 throws IOException
189 {
190
191
192 if ( isRegistered( path ) )
193 {
194 callback.refused( id, path, getOwner( path ) );
195 }
196 else
197 {
198 doRegister( id, path );
199
200 if ( cache.getOwner( path ) == null )
201 {
202 callback.registered( id, path );
203
204 }
205 else if ( cache.getOwner( path ).equals( id ) )
206 {
207 callback.alreadyRegistered( id, path );
208 }
209 else if ( getOwners().contains( cache.getOwner( path ) ) )
210 {
211 callback.superseded( id, path, cache.getOwner( path ) );
212 }
213 else
214 {
215 callback.supersededUnknownOwner( id, path, cache.getOwner( path ) );
216 }
217 }
218 }
219
220
221
222
223
224
225
226 public String getOwner( String path )
227 {
228 if ( !isRegistered( path ) )
229 {
230 return null;
231 }
232 else
233 {
234 for ( final String owner : registeredFiles.keySet() )
235 {
236 final PathSet structure = getStructure( owner );
237 if ( structure.contains( path ) )
238 {
239 return owner;
240 }
241
242 }
243 throw new IllegalStateException( "Should not happen, path [" + path
244 + "] is flagged as being registered but was not found." );
245 }
246
247 }
248
249
250
251
252
253
254
255
256
257
258 public Set<String> getOwners()
259 {
260 return registeredFiles.keySet();
261 }
262
263
264
265
266
267
268 public PathSet getFullStructure()
269 {
270 return allFiles;
271 }
272
273
274
275
276
277
278
279 public PathSet getStructure( String id )
280 {
281 PathSet pathSet = registeredFiles.get( id );
282 if ( pathSet == null )
283 {
284 pathSet = new PathSet();
285 registeredFiles.put( id, pathSet );
286 }
287 return pathSet;
288 }
289
290
291
292
293
294
295 public void analyseDependencies( DependenciesAnalysisCallback callback )
296 {
297 if ( callback == null )
298 {
299 throw new NullPointerException( "Callback could not be null." );
300 }
301 if ( cache == null )
302 {
303
304 return;
305 }
306
307 final List<Dependency> currentDependencies = new ArrayList<Dependency>( getDependencies() );
308 final List<Dependency> previousDependencies = new ArrayList<Dependency>( cache.getDependencies() );
309 final Iterator<Dependency> it = currentDependencies.listIterator();
310 while ( it.hasNext() )
311 {
312 Dependency dependency = it.next();
313
314
315 final Dependency matchingDependency = matchDependency( previousDependencies, dependency );
316 if ( matchingDependency != null )
317 {
318 callback.unchangedDependency( dependency );
319
320 it.remove();
321 previousDependencies.remove( matchingDependency );
322 }
323 else
324 {
325
326 final Dependency previousDep = findDependency( dependency, previousDependencies );
327 if ( previousDep == null )
328 {
329 callback.newDependency( dependency );
330 it.remove();
331 }
332 else if ( !dependency.getVersion().equals( previousDep.getVersion() ) )
333 {
334 callback.updatedVersion( dependency, previousDep.getVersion() );
335 it.remove();
336 previousDependencies.remove( previousDep );
337 }
338 else if ( !dependency.getScope().equals( previousDep.getScope() ) )
339 {
340 callback.updatedScope( dependency, previousDep.getScope() );
341 it.remove();
342 previousDependencies.remove( previousDep );
343 }
344 else if ( dependency.isOptional() != previousDep.isOptional() )
345 {
346 callback.updatedOptionalFlag( dependency, previousDep.isOptional() );
347 it.remove();
348 previousDependencies.remove( previousDep );
349 }
350 else
351 {
352 callback.updatedUnknown( dependency, previousDep );
353 it.remove();
354 previousDependencies.remove( previousDep );
355 }
356 }
357 }
358 for ( Dependency dependency : previousDependencies )
359 {
360 callback.removedDependency( dependency );
361 }
362 }
363
364
365
366
367
368
369
370 public void registerTargetFileName( Artifact artifact, String targetFileName )
371 {
372 if ( dependenciesInfo != null )
373 {
374 for ( DependencyInfo dependencyInfo : dependenciesInfo )
375 {
376 if ( WarUtils.isRelated( artifact, dependencyInfo.getDependency() ) )
377 {
378 dependencyInfo.setTargetFileName( targetFileName );
379 }
380 }
381 }
382 }
383
384
385
386
387
388
389
390
391
392
393 public String getCachedTargetFileName( Dependency dependency )
394 {
395 if ( cache == null )
396 {
397 return null;
398 }
399 for ( DependencyInfo dependencyInfo : cache.getDependenciesInfo() )
400 {
401 final Dependency dependency2 = dependencyInfo.getDependency();
402 if ( StringUtils.equals( dependency.getGroupId(), dependency2.getGroupId() )
403 && StringUtils.equals( dependency.getArtifactId(), dependency2.getArtifactId() )
404 && StringUtils.equals( dependency.getType(), dependency2.getType() )
405 && StringUtils.equals( dependency.getClassifier(), dependency2.getClassifier() ) )
406 {
407
408 return dependencyInfo.getTargetFileName();
409
410 }
411 }
412 return null;
413 }
414
415
416
417 private void doRegister( String id, String path )
418 {
419 getFullStructure().add( path );
420 getStructure( id ).add( path );
421 }
422
423
424
425
426
427
428
429
430 private Dependency findDependency( Dependency dependency, List<Dependency> dependencies )
431 {
432 for ( Dependency dep : dependencies )
433 {
434 if ( dependency.getGroupId().equals( dep.getGroupId() )
435 && dependency.getArtifactId().equals( dep.getArtifactId() )
436 && dependency.getType().equals( dep.getType() )
437 && (
438 ( dependency.getClassifier() == null && dep.getClassifier() == null )
439 || ( dependency.getClassifier() != null && dependency.getClassifier().equals( dep.getClassifier() ) ) ) )
440 {
441 return dep;
442 }
443 }
444 return null;
445 }
446
447 private Dependency matchDependency( List<Dependency> dependencies, Dependency dependency )
448 {
449 for ( Dependency dep : dependencies )
450 {
451 if ( WarUtils.dependencyEquals( dep, dependency ) )
452 {
453 return dep;
454 }
455
456 }
457 return null;
458 }
459
460 private List<DependencyInfo> createDependenciesInfoList( List<Dependency> dependencies )
461 {
462 if ( dependencies == null )
463 {
464 return Collections.emptyList();
465 }
466 final List<DependencyInfo> result = new ArrayList<DependencyInfo>();
467 for ( Dependency dependency : dependencies )
468 {
469 result.add( new DependencyInfo( dependency ) );
470 }
471 return result;
472 }
473
474 private Object readResolve()
475 {
476
477 this.allFiles = new PathSet();
478 for ( PathSet pathSet : registeredFiles.values() )
479 {
480 this.allFiles.addAll( pathSet );
481 }
482 return this;
483 }
484
485
486
487
488 public interface RegistrationCallback
489 {
490
491
492
493
494
495
496
497
498
499
500 void registered( String ownerId, String targetFilename )
501 throws IOException;
502
503
504
505
506
507
508
509
510
511
512 void alreadyRegistered( String ownerId, String targetFilename )
513 throws IOException;
514
515
516
517
518
519
520
521
522
523
524
525
526 void refused( String ownerId, String targetFilename, String actualOwnerId )
527 throws IOException;
528
529
530
531
532
533
534
535
536
537
538
539
540
541 void superseded( String ownerId, String targetFilename, String deprecatedOwnerId )
542 throws IOException;
543
544
545
546
547
548
549
550
551
552
553
554
555
556 void supersededUnknownOwner( String ownerId, String targetFilename, String unknownOwnerId )
557 throws IOException;
558 }
559
560
561
562
563 public interface DependenciesAnalysisCallback
564 {
565
566
567
568
569
570
571 void unchangedDependency( Dependency dependency );
572
573
574
575
576
577
578 void newDependency( Dependency dependency );
579
580
581
582
583
584
585 void removedDependency( Dependency dependency );
586
587
588
589
590
591
592
593 void updatedVersion( Dependency dependency, String previousVersion );
594
595
596
597
598
599
600
601 void updatedScope( Dependency dependency, String previousScope );
602
603
604
605
606
607
608
609 void updatedOptionalFlag( Dependency dependency, boolean previousOptional );
610
611
612
613
614
615
616
617 void updatedUnknown( Dependency dependency, Dependency previousDep );
618
619 }
620 }