1 package org.apache.maven.plugins.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
259 public Set<String> getOwners()
260 {
261 return registeredFiles.keySet();
262 }
263
264
265
266
267
268
269 public PathSet getFullStructure()
270 {
271 return allFiles;
272 }
273
274
275
276
277
278
279
280 public PathSet getStructure( String id )
281 {
282 PathSet pathSet = registeredFiles.get( id );
283 if ( pathSet == null )
284 {
285 pathSet = new PathSet();
286 registeredFiles.put( id, pathSet );
287 }
288 return pathSet;
289 }
290
291
292
293
294
295
296 public void analyseDependencies( DependenciesAnalysisCallback callback )
297 {
298 if ( callback == null )
299 {
300 throw new NullPointerException( "Callback could not be null." );
301 }
302 if ( cache == null )
303 {
304
305 return;
306 }
307
308 final List<Dependency> currentDependencies = new ArrayList<Dependency>( getDependencies() );
309 final List<Dependency> previousDependencies = new ArrayList<Dependency>( cache.getDependencies() );
310 final Iterator<Dependency> it = currentDependencies.listIterator();
311 while ( it.hasNext() )
312 {
313 Dependency dependency = it.next();
314
315
316 final Dependency matchingDependency = matchDependency( previousDependencies, dependency );
317 if ( matchingDependency != null )
318 {
319 callback.unchangedDependency( dependency );
320
321 it.remove();
322 previousDependencies.remove( matchingDependency );
323 }
324 else
325 {
326
327 final Dependency previousDep = findDependency( dependency, previousDependencies );
328 if ( previousDep == null )
329 {
330 callback.newDependency( dependency );
331 it.remove();
332 }
333 else if ( !dependency.getVersion().equals( previousDep.getVersion() ) )
334 {
335 callback.updatedVersion( dependency, previousDep.getVersion() );
336 it.remove();
337 previousDependencies.remove( previousDep );
338 }
339 else if ( !dependency.getScope().equals( previousDep.getScope() ) )
340 {
341 callback.updatedScope( dependency, previousDep.getScope() );
342 it.remove();
343 previousDependencies.remove( previousDep );
344 }
345 else if ( dependency.isOptional() != previousDep.isOptional() )
346 {
347 callback.updatedOptionalFlag( dependency, previousDep.isOptional() );
348 it.remove();
349 previousDependencies.remove( previousDep );
350 }
351 else
352 {
353 callback.updatedUnknown( dependency, previousDep );
354 it.remove();
355 previousDependencies.remove( previousDep );
356 }
357 }
358 }
359 for ( Dependency dependency : previousDependencies )
360 {
361 callback.removedDependency( dependency );
362 }
363 }
364
365
366
367
368
369
370
371 public void registerTargetFileName( Artifact artifact, String targetFileName )
372 {
373 if ( dependenciesInfo != null )
374 {
375 for ( DependencyInfo dependencyInfo : dependenciesInfo )
376 {
377 if ( WarUtils.isRelated( artifact, dependencyInfo.getDependency() ) )
378 {
379 dependencyInfo.setTargetFileName( targetFileName );
380 }
381 }
382 }
383 }
384
385
386
387
388
389
390
391
392
393
394
395 public String getCachedTargetFileName( Dependency dependency )
396 {
397 if ( cache == null )
398 {
399 return null;
400 }
401 for ( DependencyInfo dependencyInfo : cache.getDependenciesInfo() )
402 {
403 final Dependency dependency2 = dependencyInfo.getDependency();
404 if ( StringUtils.equals( dependency.getGroupId(), dependency2.getGroupId() )
405 && StringUtils.equals( dependency.getArtifactId(), dependency2.getArtifactId() )
406 && StringUtils.equals( dependency.getType(), dependency2.getType() )
407 && StringUtils.equals( dependency.getClassifier(), dependency2.getClassifier() ) )
408 {
409
410 return dependencyInfo.getTargetFileName();
411
412 }
413 }
414 return null;
415 }
416
417
418
419 private void doRegister( String id, String path )
420 {
421 getFullStructure().add( path );
422 getStructure( id ).add( path );
423 }
424
425
426
427
428
429
430
431
432 private Dependency findDependency( Dependency dependency, List<Dependency> dependencies )
433 {
434
435 for ( Dependency dep : dependencies )
436 {
437 if ( dependency.getGroupId().equals( dep.getGroupId() )
438 && dependency.getArtifactId().equals( dep.getArtifactId() )
439 && dependency.getType().equals( dep.getType() )
440 && (
441 ( dependency.getClassifier() == null && dep.getClassifier() == null )
442 || ( dependency.getClassifier() != null && dependency.getClassifier().equals( dep.getClassifier() ) ) ) )
443 {
444 return dep;
445 }
446 }
447 return null;
448
449 }
450
451 private Dependency matchDependency( List<Dependency> dependencies, Dependency dependency )
452 {
453 for ( Dependency dep : dependencies )
454 {
455 if ( WarUtils.dependencyEquals( dep, dependency ) )
456 {
457 return dep;
458 }
459
460 }
461 return null;
462 }
463
464 private List<DependencyInfo> createDependenciesInfoList( List<Dependency> dependencies )
465 {
466 if ( dependencies == null )
467 {
468 return Collections.emptyList();
469 }
470 final List<DependencyInfo> result = new ArrayList<DependencyInfo>();
471 for ( Dependency dependency : dependencies )
472 {
473 result.add( new DependencyInfo( dependency ) );
474 }
475 return result;
476 }
477
478 private Object readResolve()
479 {
480
481 this.allFiles = new PathSet();
482 for ( PathSet pathSet : registeredFiles.values() )
483 {
484 this.allFiles.addAll( pathSet );
485 }
486 return this;
487 }
488
489
490
491
492 public interface RegistrationCallback
493 {
494
495
496
497
498
499
500
501
502
503
504 void registered( String ownerId, String targetFilename )
505 throws IOException;
506
507
508
509
510
511
512
513
514
515
516 void alreadyRegistered( String ownerId, String targetFilename )
517 throws IOException;
518
519
520
521
522
523
524
525
526
527
528
529
530
531 void refused( String ownerId, String targetFilename, String actualOwnerId )
532 throws IOException;
533
534
535
536
537
538
539
540
541
542
543
544
545
546 void superseded( String ownerId, String targetFilename, String deprecatedOwnerId )
547 throws IOException;
548
549
550
551
552
553
554
555
556
557
558
559
560
561 void supersededUnknownOwner( String ownerId, String targetFilename, String unknownOwnerId )
562 throws IOException;
563 }
564
565
566
567
568 public interface DependenciesAnalysisCallback
569 {
570
571
572
573
574
575
576 void unchangedDependency( Dependency dependency );
577
578
579
580
581
582
583 void newDependency( Dependency dependency );
584
585
586
587
588
589
590 void removedDependency( Dependency dependency );
591
592
593
594
595
596
597
598 void updatedVersion( Dependency dependency, String previousVersion );
599
600
601
602
603
604
605
606 void updatedScope( Dependency dependency, String previousScope );
607
608
609
610
611
612
613
614 void updatedOptionalFlag( Dependency dependency, boolean previousOptional );
615
616
617
618
619
620
621
622 void updatedUnknown( Dependency dependency, Dependency previousDep );
623
624 }
625 }