1 package org.apache.archiva.proxy;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.configuration.ArchivaConfiguration;
23 import org.apache.archiva.configuration.NetworkProxyConfiguration;
24 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
25 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
26 import org.apache.archiva.policies.CachedFailuresPolicy;
27 import org.apache.archiva.policies.ChecksumPolicy;
28 import org.apache.archiva.policies.PropagateErrorsDownloadPolicy;
29 import org.apache.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy;
30 import org.apache.archiva.policies.ReleasesPolicy;
31 import org.apache.archiva.policies.SnapshotsPolicy;
32 import org.apache.archiva.proxy.model.RepositoryProxyHandler;
33 import org.apache.archiva.repository.content.BaseRepositoryContentLayout;
34 import org.apache.archiva.repository.ManagedRepository;
35 import org.apache.archiva.repository.ManagedRepositoryContent;
36 import org.apache.archiva.repository.RepositoryRegistry;
37 import org.apache.archiva.repository.base.BasicManagedRepository;
38 import org.apache.archiva.repository.content.Artifact;
39 import org.apache.archiva.repository.storage.StorageAsset;
40 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
41 import org.apache.commons.io.FileUtils;
42 import org.apache.commons.lang3.StringUtils;
43 import org.apache.maven.wagon.Wagon;
44 import org.apache.maven.wagon.providers.http.HttpWagon;
45 import org.eclipse.jetty.server.Handler;
46 import org.eclipse.jetty.server.HttpConnectionFactory;
47 import org.eclipse.jetty.server.Request;
48 import org.eclipse.jetty.server.Server;
49 import org.eclipse.jetty.server.ServerConnector;
50 import org.eclipse.jetty.server.handler.AbstractHandler;
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.springframework.context.ApplicationContext;
56 import org.springframework.test.context.ContextConfiguration;
58 import javax.inject.Inject;
59 import javax.servlet.ServletException;
60 import javax.servlet.http.HttpServletRequest;
61 import javax.servlet.http.HttpServletResponse;
62 import java.io.IOException;
63 import java.nio.charset.Charset;
64 import java.nio.file.Files;
65 import java.nio.file.Path;
66 import java.nio.file.Paths;
68 import static org.junit.Assert.*;
71 * Integration test for connecting over a HTTP proxy.
75 @RunWith( ArchivaSpringJUnit4ClassRunner.class )
76 @ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath:/spring-context.xml" } )
77 public class HttpProxyTransferTest
79 private static final String PROXY_ID = "proxy";
81 private static final String MANAGED_ID = "default-managed-repository";
83 private static final String PROXIED_ID = "proxied1";
85 private static final String PROXIED_BASEDIR = "src/test/repositories/proxied1";
87 private RepositoryProxyHandler proxyHandler;
89 private ManagedRepositoryContent managedDefaultRepository;
92 private ApplicationContext applicationContext;
95 private RepositoryRegistry repositoryRegistry;
98 private ArchivaConfiguration config;
101 private ProxyRegistry proxyRegistry;
103 private Server server;
105 protected ManagedRepositoryContent createRepository( String id, String name, String path, String layout )
108 ManagedRepository repo = BasicManagedRepository.newFilesystemInstance(id, name, Paths.get(path).resolve(id));
109 repositoryRegistry.putRepository(repo);
110 return repositoryRegistry.getManagedRepository(id).getContent();
117 proxyHandler = applicationContext.getBean( "repositoryProxyHandler#test", RepositoryProxyHandler.class );
119 // clear from previous tests - TODO the spring context should be initialised per test instead, or the config
120 // made a complete mock
121 config.getConfiguration().getProxyConnectors().clear();
123 // Setup source repository (using default layout)
124 String repoPath = "target/test-repository/managed/" + getClass().getSimpleName();
126 Path destRepoDir = Paths.get( repoPath );
128 // Cleanout destination dirs.
129 if ( Files.exists(destRepoDir))
131 FileUtils.deleteDirectory( destRepoDir.toFile() );
134 // Make the destination dir.
135 Files.createDirectories(destRepoDir);
138 Handler handler = new AbstractHandler()
141 public void handle( String s, Request request, HttpServletRequest httpServletRequest,
142 HttpServletResponse response )
143 throws IOException, ServletException
145 response.setContentType( "text/plain" );
146 response.setStatus( HttpServletResponse.SC_OK );
147 response.getWriter().print( "get-default-layout-1.0.jar\n\n" );
148 assertNotNull( request.getHeader( "Proxy-Connection" ) );
150 ( (Request) request ).setHandled( true );
153 public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch )
154 throws IOException, ServletException
156 response.setContentType( "text/plain" );
157 response.setStatus( HttpServletResponse.SC_OK );
158 response.getWriter().print( "get-default-layout-1.0.jar\n\n" );
159 assertNotNull( request.getHeader( "Proxy-Connection" ) );
161 ( (Request) request ).setHandled( true );
165 server = new Server( );
166 ServerConnector serverConnector = new ServerConnector( server, new HttpConnectionFactory());
167 server.addConnector( serverConnector );
168 server.setHandler( handler );
171 int port = serverConnector.getLocalPort();
173 NetworkProxyConfiguration proxyConfig = new NetworkProxyConfiguration();
174 proxyConfig.setHost( "localhost" );
175 proxyConfig.setPort( port );
176 proxyConfig.setProtocol( "http" );
177 proxyConfig.setId( PROXY_ID );
178 config.getConfiguration().addNetworkProxy( proxyConfig );
179 ( (MockConfiguration) config ).triggerChange("networkProxies.networkProxy(0).host", "localhost");
181 // Setup target (proxied to) repository.
182 RemoteRepositoryConfiguration repoConfig = new RemoteRepositoryConfiguration();
184 repoConfig.setId( PROXIED_ID );
185 repoConfig.setName( "Proxied Repository 1" );
186 repoConfig.setLayout( "default" );
187 repoConfig.setUrl( "http://www.example.com/" );
189 config.getConfiguration().addRemoteRepository( repoConfig );
191 Wagon wagon = new HttpWagon( );
192 WagonDelegate delegate = (WagonDelegate) applicationContext.getBean( "wagon#http", Wagon.class );
193 delegate.setDelegate( wagon );
195 proxyRegistry.reload();
196 repositoryRegistry.reload();
198 managedDefaultRepository = createRepository(MANAGED_ID, "Default Managed Repository", repoPath, "default");
203 public void tearDown()
212 public void testGetOverHttpProxy()
215 assertTrue( StringUtils.isEmpty( System.getProperty( "http.proxyHost" , "" ) ));
216 assertTrue( StringUtils.isEmpty( System.getProperty( "http.proxyPort", "" ) ) );
218 String path = "org/apache/maven/test/get-default-layout/1.0/get-default-layout-1.0.jar";
220 // Configure Connector (usually done within archiva.xml configuration)
223 managedDefaultRepository = repositoryRegistry.getManagedRepository(MANAGED_ID).getContent();
225 BaseRepositoryContentLayout layout = managedDefaultRepository.getLayout( BaseRepositoryContentLayout.class );
226 Path expectedFile = managedDefaultRepository.getRepository().getRoot().resolve( path ).getFilePath();
227 Files.deleteIfExists( expectedFile );
228 Artifact artifact = layout.getArtifact( path );
230 // Attempt the proxy fetch.
231 StorageAsset downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository.getRepository(), artifact );
233 Path sourceFile = Paths.get( PROXIED_BASEDIR, path );
234 assertNotNull( "Expected File should not be null.", expectedFile );
235 assertNotNull( "Actual File should not be null.", downloadedFile );
237 assertTrue( "Check actual file exists.", Files.exists(downloadedFile.getFilePath()));
238 assertTrue( "Check filename path is appropriate.", Files.isSameFile( expectedFile, downloadedFile.getFilePath()));
239 assertTrue( "Check file path matches.", Files.isSameFile( expectedFile, downloadedFile.getFilePath()));
241 String expectedContents = FileUtils.readFileToString( sourceFile.toFile(), Charset.defaultCharset() );
242 String actualContents = FileUtils.readFileToString( downloadedFile.getFilePath().toFile(), Charset.defaultCharset() );
243 assertEquals( "Check file contents.", expectedContents, actualContents );
245 assertTrue( StringUtils.isEmpty( System.getProperty( "http.proxyHost", "" ) ) );
246 assertTrue( StringUtils.isEmpty( System.getProperty( "http.proxyPort" , "") ) );
249 private void addConnector()
251 ProxyConnectorConfiguration connectorConfig = new ProxyConnectorConfiguration();
252 connectorConfig.setProxyId( PROXY_ID );
253 connectorConfig.setSourceRepoId( MANAGED_ID );
254 connectorConfig.setTargetRepoId( PROXIED_ID );
255 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CHECKSUM, ChecksumPolicy.FIX.getId() );
256 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_RELEASES, ReleasesPolicy.ONCE.getId() );
257 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_SNAPSHOTS, SnapshotsPolicy.ONCE.getId() );
258 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CACHE_FAILURES, CachedFailuresPolicy.NO.getId() );
259 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS,
260 PropagateErrorsDownloadPolicy.QUEUE.getId() );
261 connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS_ON_UPDATE,
262 PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT.getId() );
264 int count = config.getConfiguration().getProxyConnectors().size();
265 config.getConfiguration().addProxyConnector( connectorConfig );
267 // Proper Triggering ...
268 String prefix = "proxyConnectors.proxyConnector(" + count + ")";
269 ( (MockConfiguration) config ).triggerChange( prefix + ".sourceRepoId", connectorConfig.getSourceRepoId() );