1 package org.apache.archiva.proxy;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import net.sf.ehcache.CacheManager;
23 import org.apache.archiva.admin.model.beans.ManagedRepository;
24 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
25 import org.apache.archiva.admin.repository.managed.DefaultManagedRepositoryAdmin;
26 import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
27 import org.apache.archiva.configuration.ArchivaConfiguration;
28 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
29 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
30 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
31 import org.apache.archiva.policies.CachedFailuresPolicy;
32 import org.apache.archiva.policies.ChecksumPolicy;
33 import org.apache.archiva.policies.PropagateErrorsDownloadPolicy;
34 import org.apache.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy;
35 import org.apache.archiva.policies.ReleasesPolicy;
36 import org.apache.archiva.policies.SnapshotsPolicy;
37 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
38 import org.apache.archiva.repository.ManagedRepositoryContent;
39 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
40 import org.apache.commons.io.FileUtils;
41 import org.apache.maven.index.NexusIndexer;
42 import org.apache.maven.index.context.IndexingContext;
43 import org.apache.maven.wagon.Wagon;
44 import org.easymock.EasyMock;
45 import org.easymock.IMocksControl;
46 import org.junit.After;
47 import org.junit.Before;
48 import org.junit.runner.RunWith;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.context.ApplicationContext;
52 import org.springframework.test.context.ContextConfiguration;
53
54 import javax.inject.Inject;
55 import java.io.BufferedReader;
56 import java.io.File;
57 import java.io.FileReader;
58 import java.io.IOException;
59 import java.nio.charset.Charset;
60 import java.text.ParseException;
61 import java.text.SimpleDateFormat;
62 import java.util.ArrayList;
63 import java.util.Calendar;
64 import java.util.Collection;
65 import java.util.Date;
66 import java.util.Locale;
67
68 import static org.junit.Assert.*;
69
70
71
72
73 @RunWith( ArchivaSpringJUnit4ClassRunner.class )
74 @ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath:/spring-context.xml" } )
75 public abstract class AbstractProxyTestCase
76 {
77 @Inject
78 protected ApplicationContext applicationContext;
79
80 protected static final String ID_PROXIED1 = "proxied1";
81
82 protected static final String ID_PROXIED1_TARGET = "proxied1-target";
83
84 protected static final String ID_PROXIED2 = "proxied2";
85
86 protected static final String ID_PROXIED2_TARGET = "proxied2-target";
87
88 protected static final String ID_DEFAULT_MANAGED = "default-managed-repository";
89
90 protected static final String REPOPATH_PROXIED1 = "src/test/repositories/proxied1";
91
92 protected static final String REPOPATH_PROXIED1_TARGET = "target/test-repository/proxied1";
93
94 protected static final String REPOPATH_PROXIED2 = "src/test/repositories/proxied2";
95
96 protected static final String REPOPATH_PROXIED2_TARGET = "target/test-repository/proxied2";
97
98 protected static final String REPOPATH_DEFAULT_MANAGED = "src/test/repositories/managed";
99
100
101
102 protected IMocksControl wagonMockControl;
103
104 protected Wagon wagonMock;
105
106
107 protected RepositoryProxyConnectors proxyHandler;
108
109 protected ManagedRepositoryContent managedDefaultRepository;
110
111 protected File managedDefaultDir;
112
113 protected MockConfiguration config;
114
115 protected Logger log = LoggerFactory.getLogger( getClass() );
116
117 WagonDelegate delegate;
118
119 @Inject
120 protected ManagedRepositoryAdmin managedRepositoryAdmin;
121
122 @Inject
123 protected PlexusSisuBridge plexusSisuBridge;
124
125 @Before
126 public void setUp()
127 throws Exception
128 {
129 config =
130 (MockConfiguration) applicationContext.getBean( "archivaConfiguration#mock", ArchivaConfiguration.class );
131
132 config.getConfiguration().setManagedRepositories( new ArrayList<ManagedRepositoryConfiguration>() );
133 config.getConfiguration().setRemoteRepositories( new ArrayList<RemoteRepositoryConfiguration>() );
134 config.getConfiguration().setProxyConnectors( new ArrayList<ProxyConnectorConfiguration>() );
135
136
137 String name = getClass().getSimpleName();
138 String repoPath = "target/test-repository/managed/" + name;
139
140 managedDefaultRepository =
141 createRepository( ID_DEFAULT_MANAGED, "Default Managed Repository", repoPath, "default" );
142
143 managedDefaultDir = new File( managedDefaultRepository.getRepoRoot() );
144
145 ManagedRepository repoConfig = managedDefaultRepository.getRepository();
146
147 ( (DefaultManagedRepositoryAdmin) applicationContext.getBean(
148 ManagedRepositoryAdmin.class ) ).setArchivaConfiguration( config );
149
150 applicationContext.getBean( ManagedRepositoryAdmin.class ).addManagedRepository( repoConfig, false, null );
151
152
153 removeMavenIndexes();
154
155 ManagedRepositoryAdmin managedRepositoryAdmin = applicationContext.getBean( ManagedRepositoryAdmin.class );
156
157 if ( managedRepositoryAdmin.getManagedRepository( repoConfig.getId() ) != null )
158 {
159 managedRepositoryAdmin.deleteManagedRepository( repoConfig.getId(), null, true );
160 }
161
162 managedRepositoryAdmin.addManagedRepository( repoConfig, false, null );
163
164
165 saveRemoteRepositoryConfig( ID_PROXIED1, "Proxied Repository 1",
166 new File( REPOPATH_PROXIED1 ).toURL().toExternalForm(), "default" );
167
168
169 saveRemoteRepositoryConfig( ID_PROXIED2, "Proxied Repository 2",
170 new File( REPOPATH_PROXIED2 ).toURL().toExternalForm(), "default" );
171
172
173
174
175 proxyHandler = applicationContext.getBean( "repositoryProxyConnectors#test", RepositoryProxyConnectors.class );
176
177
178 wagonMockControl = EasyMock.createNiceControl();
179 wagonMock = wagonMockControl.createMock( Wagon.class );
180
181 delegate = (WagonDelegate) applicationContext.getBean( "wagon#test", Wagon.class );
182
183 delegate.setDelegate( wagonMock );
184
185 CacheManager.getInstance().clearAll();
186
187 log.info( "\n.\\ {}() \\._________________________________________\n", name );
188 }
189
190 @After
191 public void shutdown()
192 throws Exception
193 {
194 removeMavenIndexes();
195 }
196
197
198 protected void removeMavenIndexes()
199 throws Exception
200 {
201 NexusIndexer nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class );
202
203 for ( IndexingContext indexingContext : nexusIndexer.getIndexingContexts().values() )
204 {
205 nexusIndexer.removeIndexingContext( indexingContext, false );
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 protected void assertChecksums( File expectedFile, String expectedSha1Contents, String expectedMd5Contents )
264 throws Exception
265 {
266 File sha1File = new File( expectedFile.getAbsolutePath() + ".sha1" );
267 File md5File = new File( expectedFile.getAbsolutePath() + ".md5" );
268
269 if ( expectedSha1Contents == null )
270 {
271 assertFalse( "SHA1 File should NOT exist: " + sha1File.getPath(), sha1File.exists() );
272 }
273 else
274 {
275 assertTrue( "SHA1 File should exist: " + sha1File.getPath(), sha1File.exists() );
276 String actualSha1Contents = readChecksumFile( sha1File );
277 assertEquals( "SHA1 File contents: " + sha1File.getPath(), expectedSha1Contents, actualSha1Contents );
278 }
279
280 if ( expectedMd5Contents == null )
281 {
282 assertFalse( "MD5 File should NOT exist: " + md5File.getPath(), md5File.exists() );
283 }
284 else
285 {
286 assertTrue( "MD5 File should exist: " + md5File.getPath(), md5File.exists() );
287 String actualMd5Contents = readChecksumFile( md5File );
288 assertEquals( "MD5 File contents: " + md5File.getPath(), expectedMd5Contents, actualMd5Contents );
289 }
290 }
291
292 protected void assertFileEquals( File expectedFile, File actualFile, File sourceFile )
293 throws Exception
294 {
295 assertNotNull( "Expected File should not be null.", expectedFile );
296 assertNotNull( "Actual File should not be null.", actualFile );
297
298 assertTrue( "Check actual file exists.", actualFile.exists() );
299 assertEquals( "Check filename path is appropriate.", expectedFile.getCanonicalPath(),
300 actualFile.getCanonicalPath() );
301 assertEquals( "Check file path matches.", expectedFile.getAbsolutePath(), actualFile.getAbsolutePath() );
302
303 String expectedContents =
304 org.apache.commons.io.FileUtils.readFileToString( sourceFile, Charset.defaultCharset() );
305 String actualContents =
306 org.apache.commons.io.FileUtils.readFileToString( actualFile, Charset.defaultCharset() );
307 assertEquals( "Check file contents.", expectedContents, actualContents );
308 }
309
310 protected void assertNotDownloaded( File downloadedFile )
311 {
312 assertNull( "Found file: " + downloadedFile + "; but was expecting a failure", downloadedFile );
313 }
314
315 @SuppressWarnings( "unchecked" )
316 protected void assertNoTempFiles( File expectedFile )
317 {
318 File workingDir = expectedFile.getParentFile();
319 if ( ( workingDir == null ) || !workingDir.isDirectory() )
320 {
321 return;
322 }
323
324 Collection<File> tmpFiles =
325 org.apache.commons.io.FileUtils.listFiles( workingDir, new String[]{ "tmp" }, false );
326 if ( !tmpFiles.isEmpty() )
327 {
328 StringBuilder emsg = new StringBuilder();
329 emsg.append( "Found Temp Files in dir: " ).append( workingDir.getPath() );
330 for ( File tfile : tmpFiles )
331 {
332 emsg.append( "\n " ).append( tfile.getName() );
333 }
334 fail( emsg.toString() );
335 }
336 }
337
338
339
340
341
342
343
344
345
346 protected void copyDirectoryStructure( File sourceDirectory, File destDirectory )
347 throws IOException
348 {
349 if ( !sourceDirectory.exists() )
350 {
351 throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." );
352 }
353
354 File[] files = sourceDirectory.listFiles();
355
356 String sourcePath = sourceDirectory.getAbsolutePath();
357
358 for ( int i = 0; i < files.length; i++ )
359 {
360 File file = files[i];
361
362 String dest = file.getAbsolutePath();
363
364 dest = dest.substring( sourcePath.length() + 1 );
365
366 File destination = new File( destDirectory, dest );
367
368 if ( file.isFile() )
369 {
370 destination = destination.getParentFile();
371
372 org.apache.commons.io.FileUtils.copyFile( file, new File( destination, file.getName() ), false );
373
374
375 }
376 else if ( file.isDirectory() )
377 {
378 if ( !".svn".equals( file.getName() ) )
379 {
380 if ( !destination.exists() && !destination.mkdirs() )
381 {
382 throw new IOException(
383 "Could not create destination directory '" + destination.getAbsolutePath() + "'." );
384 }
385
386 copyDirectoryStructure( file, destination );
387 }
388 }
389 else
390 {
391 throw new IOException( "Unknown file type: " + file.getAbsolutePath() );
392 }
393 }
394 }
395
396
397 protected ManagedRepositoryContent createRepository( String id, String name, String path, String layout )
398 throws Exception
399 {
400 ManagedRepository repo = new ManagedRepository();
401 repo.setId( id );
402 repo.setName( name );
403 repo.setLocation( path );
404 repo.setLayout( layout );
405
406 ManagedRepositoryContent repoContent =
407 applicationContext.getBean( "managedRepositoryContent#" + layout, ManagedRepositoryContent.class );
408 repoContent.setRepository( repo );
409 return repoContent;
410 }
411
412
413
414
415 protected String readChecksumFile( File checksumFile )
416 throws Exception
417 {
418 FileReader freader = null;
419 BufferedReader buf = null;
420
421 try
422 {
423 freader = new FileReader( checksumFile );
424 buf = new BufferedReader( freader );
425 return buf.readLine();
426 }
427 finally
428 {
429 if ( buf != null )
430 {
431 buf.close();
432 }
433
434 if ( freader != null )
435 {
436 freader.close();
437 }
438 }
439 }
440
441 protected void saveConnector( String sourceRepoId, String targetRepoId, boolean disabled )
442 {
443 saveConnector( sourceRepoId, targetRepoId, ChecksumPolicy.IGNORE, ReleasesPolicy.ALWAYS, SnapshotsPolicy.ALWAYS,
444 CachedFailuresPolicy.NO, disabled );
445 }
446
447 protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy,
448 String snapshotPolicy, String cacheFailuresPolicy, boolean disabled )
449 {
450 saveConnector( sourceRepoId, targetRepoId, checksumPolicy, releasePolicy, snapshotPolicy, cacheFailuresPolicy,
451 PropagateErrorsDownloadPolicy.QUEUE, disabled );
452 }
453
454 protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy,
455 String snapshotPolicy, String cacheFailuresPolicy, String errorPolicy,
456 boolean disabled )
457 {
458 saveConnector( sourceRepoId, targetRepoId, checksumPolicy, releasePolicy, snapshotPolicy, cacheFailuresPolicy,
459 errorPolicy, PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT, disabled );
460 }
461
462 protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy,
463 String snapshotPolicy, String cacheFailuresPolicy, String errorPolicy,
464 String errorOnUpdatePolicy, boolean disabled )
465 {
466 ProxyConnectorConfiguration connectorConfig = new ProxyConnectorConfiguration();
467 connectorConfig.setSourceRepoId( sourceRepoId );
468 connectorConfig.setTargetRepoId( targetRepoId );
469 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CHECKSUM, checksumPolicy );
470 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_RELEASES, releasePolicy );
471 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_SNAPSHOTS, snapshotPolicy );
472 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CACHE_FAILURES, cacheFailuresPolicy );
473 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS, errorPolicy );
474 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS_ON_UPDATE, errorOnUpdatePolicy );
475 connectorConfig.setDisabled( disabled );
476
477 int count = config.getConfiguration().getProxyConnectors().size();
478 config.getConfiguration().addProxyConnector( connectorConfig );
479
480
481 String prefix = "proxyConnectors.proxyConnector(" + count + ")";
482 config.triggerChange( prefix + ".sourceRepoId", connectorConfig.getSourceRepoId() );
483 config.triggerChange( prefix + ".targetRepoId", connectorConfig.getTargetRepoId() );
484 config.triggerChange( prefix + ".proxyId", connectorConfig.getProxyId() );
485 config.triggerChange( prefix + ".policies.releases", connectorConfig.getPolicy( "releases", "" ) );
486 config.triggerChange( prefix + ".policies.checksum", connectorConfig.getPolicy( "checksum", "" ) );
487 config.triggerChange( prefix + ".policies.snapshots", connectorConfig.getPolicy( "snapshots", "" ) );
488 config.triggerChange( prefix + ".policies.cache-failures", connectorConfig.getPolicy( "cache-failures", "" ) );
489 config.triggerChange( prefix + ".policies.propagate-errors",
490 connectorConfig.getPolicy( "propagate-errors", "" ) );
491 config.triggerChange( prefix + ".policies.propagate-errors-on-update",
492 connectorConfig.getPolicy( "propagate-errors-on-update", "" ) );
493 }
494
495 protected void saveManagedRepositoryConfig( String id, String name, String path, String layout )
496 {
497 ManagedRepositoryConfiguration repoConfig = new ManagedRepositoryConfiguration();
498
499 repoConfig.setId( id );
500 repoConfig.setName( name );
501 repoConfig.setLayout( layout );
502
503 repoConfig.setLocation( path );
504
505 int count = config.getConfiguration().getManagedRepositories().size();
506 config.getConfiguration().addManagedRepository( repoConfig );
507
508 String prefix = "managedRepositories.managedRepository(" + count + ")";
509 config.triggerChange( prefix + ".id", repoConfig.getId() );
510 config.triggerChange( prefix + ".name", repoConfig.getName() );
511 config.triggerChange( prefix + ".location", repoConfig.getLocation() );
512 config.triggerChange( prefix + ".layout", repoConfig.getLayout() );
513 }
514
515 protected void saveRemoteRepositoryConfig( String id, String name, String url, String layout )
516 {
517 RemoteRepositoryConfiguration repoConfig = new RemoteRepositoryConfiguration();
518
519 repoConfig.setId( id );
520 repoConfig.setName( name );
521 repoConfig.setLayout( layout );
522 repoConfig.setUrl( url );
523
524 int count = config.getConfiguration().getRemoteRepositories().size();
525 config.getConfiguration().addRemoteRepository( repoConfig );
526
527 String prefix = "remoteRepositories.remoteRepository(" + count + ")";
528 config.triggerChange( prefix + ".id", repoConfig.getId() );
529 config.triggerChange( prefix + ".name", repoConfig.getName() );
530 config.triggerChange( prefix + ".url", repoConfig.getUrl() );
531 config.triggerChange( prefix + ".layout", repoConfig.getLayout() );
532 }
533
534 protected File saveTargetedRepositoryConfig( String id, String originalPath, String targetPath, String layout )
535 throws IOException
536 {
537 File repoLocation = new File( targetPath );
538 FileUtils.deleteDirectory( repoLocation );
539 copyDirectoryStructure( new File( originalPath ), repoLocation );
540
541 saveRemoteRepositoryConfig( id, "Target Repo-" + id, targetPath, layout );
542
543 return repoLocation;
544 }
545
546
547
548
549
550
551
552
553
554 protected void setupTestableManagedRepository( String resourcePath )
555 throws IOException
556 {
557 String resourceDir = resourcePath;
558
559 if ( !resourcePath.endsWith( "/" ) )
560 {
561 int idx = resourcePath.lastIndexOf( '/' );
562 resourceDir = resourcePath.substring( 0, idx );
563 }
564
565 File sourceRepoDir = new File( REPOPATH_DEFAULT_MANAGED );
566 File sourceDir = new File( sourceRepoDir, resourceDir );
567
568 File destRepoDir = managedDefaultDir;
569 File destDir = new File( destRepoDir, resourceDir );
570
571
572 if ( destDir.exists() )
573 {
574 FileUtils.deleteDirectory( destDir );
575 }
576
577
578 destDir.mkdirs();
579
580
581 if ( !sourceDir.exists() )
582 {
583
584 log.error( "[WARN] Skipping setup of testable managed repository, source dir does not exist: {}",
585 sourceDir );
586 }
587 else
588 {
589
590
591 if ( !sourceDir.isDirectory() )
592 {
593 fail( "Unable to setup testable managed repository, source is not a directory: " + sourceDir );
594 }
595
596
597 copyDirectoryStructure( sourceDir, destDir );
598 }
599 }
600
601 protected void setManagedNewerThanRemote( File managedFile, File remoteFile )
602 {
603 setManagedNewerThanRemote( managedFile, remoteFile, 55000 );
604 }
605
606 protected void setManagedNewerThanRemote( File managedFile, File remoteFile, long time )
607 {
608 assertTrue( "Managed File should exist: ", managedFile.exists() );
609 assertTrue( "Remote File should exist: ", remoteFile.exists() );
610
611 managedFile.setLastModified( remoteFile.lastModified() + time );
612
613 assertTrue( managedFile.lastModified() > remoteFile.lastModified() );
614 }
615
616 protected void setManagedOlderThanRemote( File managedFile, File remoteFile )
617 {
618 setManagedOlderThanRemote( managedFile, remoteFile, 55000 );
619 }
620
621 protected void setManagedOlderThanRemote( File managedFile, File remoteFile, long time )
622 {
623 assertTrue( "Managed File should exist: ", managedFile.exists() );
624 assertTrue( "Remote File should exist: ", remoteFile.exists() );
625
626 managedFile.setLastModified( remoteFile.lastModified() - time );
627
628 assertTrue( managedFile.lastModified() < remoteFile.lastModified() );
629
630 }
631
632 protected void assertNotModified( File file, long expectedModificationTime )
633 {
634 assertEquals( "File <" + file.getAbsolutePath() + "> not have been modified.", expectedModificationTime,
635 file.lastModified() );
636 }
637
638
639 protected void assertNotExistsInManagedDefaultRepo( File file )
640 throws Exception
641 {
642 String managedDefaultPath = managedDefaultDir.getCanonicalPath();
643 String testFile = file.getCanonicalPath();
644
645 assertTrue( "Unit Test Failure: File <" + testFile
646 + "> should be have been defined within the managed default path of <" + managedDefaultPath
647 + ">", testFile.startsWith( managedDefaultPath ) );
648
649 assertFalse( "File < " + testFile + "> should not exist in managed default repository.", file.exists() );
650 }
651
652 protected static Date getFutureDate()
653 throws ParseException
654 {
655 Calendar cal = Calendar.getInstance();
656 cal.add( Calendar.YEAR, 1 );
657 return cal.getTime();
658 }
659
660 protected static Date getPastDate()
661 throws ParseException
662 {
663 return new SimpleDateFormat( "yyyy-MM-dd", Locale.US ).parse( "2000-01-01" );
664 }
665 }