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