001package org.apache.archiva.rest.services; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.archiva.admin.model.RepositoryAdminException; 023import org.apache.archiva.admin.model.beans.RemoteRepository; 024import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin; 025import org.apache.archiva.proxy.ProxyRegistry; 026import org.apache.archiva.proxy.maven.WagonFactory; 027import org.apache.archiva.proxy.maven.WagonFactoryRequest; 028import org.apache.archiva.proxy.model.NetworkProxy; 029import org.apache.archiva.rest.api.services.ArchivaRestServiceException; 030import org.apache.archiva.rest.api.services.RemoteRepositoriesService; 031import org.apache.commons.lang3.StringUtils; 032import org.apache.maven.wagon.TransferFailedException; 033import org.apache.maven.wagon.Wagon; 034import org.apache.maven.wagon.proxy.ProxyInfo; 035import org.apache.maven.wagon.repository.Repository; 036import org.apache.maven.wagon.shared.http.AbstractHttpClientWagon; 037import org.apache.maven.wagon.shared.http.HttpConfiguration; 038import org.apache.maven.wagon.shared.http.HttpMethodConfiguration; 039import org.springframework.stereotype.Service; 040 041import javax.inject.Inject; 042import java.net.URL; 043import java.util.Collections; 044import java.util.List; 045 046/** 047 * @author Olivier Lamy 048 * @since 1.4-M1 049 */ 050@Service( "remoteRepositoriesService#rest" ) 051public class DefaultRemoteRepositoriesService 052 extends AbstractRestService 053 implements RemoteRepositoriesService { 054 055 @Inject 056 private RemoteRepositoryAdmin remoteRepositoryAdmin; 057 058 @Inject 059 private WagonFactory wagonFactory; 060 061 @Inject 062 private ProxyRegistry proxyRegistry; 063 064 int checkReadTimeout = 10000; 065 int checkTimeout = 9000; 066 067 068 @Override 069 public List<RemoteRepository> getRemoteRepositories() 070 throws ArchivaRestServiceException { 071 try { 072 List<RemoteRepository> remoteRepositories = remoteRepositoryAdmin.getRemoteRepositories(); 073 return remoteRepositories == null ? Collections.<RemoteRepository>emptyList() : remoteRepositories; 074 } catch (RepositoryAdminException e) { 075 log.error(e.getMessage(), e); 076 throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e); 077 } 078 } 079 080 @Override 081 public RemoteRepository getRemoteRepository(String repositoryId) 082 throws ArchivaRestServiceException { 083 084 List<RemoteRepository> remoteRepositories = getRemoteRepositories(); 085 for (RemoteRepository repository : remoteRepositories) { 086 if (StringUtils.equals(repositoryId, repository.getId())) { 087 return repository; 088 } 089 } 090 return null; 091 } 092 093 @Override 094 public Boolean deleteRemoteRepository(String repositoryId) 095 throws ArchivaRestServiceException { 096 try { 097 return remoteRepositoryAdmin.deleteRemoteRepository(repositoryId, getAuditInformation()); 098 } catch (RepositoryAdminException e) { 099 log.error(e.getMessage(), e); 100 throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e); 101 } 102 } 103 104 @Override 105 public Boolean addRemoteRepository(RemoteRepository remoteRepository) 106 throws ArchivaRestServiceException { 107 try { 108 return remoteRepositoryAdmin.addRemoteRepository(remoteRepository, getAuditInformation()); 109 } catch (RepositoryAdminException e) { 110 log.error(e.getMessage(), e); 111 throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e); 112 } 113 } 114 115 @Override 116 public Boolean updateRemoteRepository(RemoteRepository remoteRepository) 117 throws ArchivaRestServiceException { 118 try { 119 return remoteRepositoryAdmin.updateRemoteRepository(remoteRepository, getAuditInformation()); 120 } catch (RepositoryAdminException e) { 121 log.error(e.getMessage(), e); 122 throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e); 123 } 124 } 125 126 @Override 127 public Boolean checkRemoteConnectivity(String repositoryId) 128 throws ArchivaRestServiceException { 129 try { 130 RemoteRepository remoteRepository = remoteRepositoryAdmin.getRemoteRepository(repositoryId); 131 if (remoteRepository == null) { 132 log.warn("ignore scheduleDownloadRemote for repo with id {} as not exists", repositoryId); 133 return Boolean.FALSE; 134 } 135 NetworkProxy networkProxy = null; 136 if (StringUtils.isNotBlank(remoteRepository.getRemoteDownloadNetworkProxyId())) { 137 networkProxy = proxyRegistry.getNetworkProxy(remoteRepository.getRemoteDownloadNetworkProxyId()); 138 if (networkProxy == null) { 139 log.warn( 140 "your remote repository is configured to download remote index trought a proxy we cannot find id:{}", 141 remoteRepository.getRemoteDownloadNetworkProxyId()); 142 } 143 } 144 145 String wagonProtocol = new URL(remoteRepository.getUrl()).getProtocol(); 146 147 final Wagon wagon = 148 wagonFactory.getWagon(new WagonFactoryRequest(wagonProtocol, remoteRepository.getExtraHeaders()) // 149 .networkProxy(networkProxy)); 150 151 // hardcoded value as it's a check of the remote repo connectivity 152 wagon.setReadTimeout(checkReadTimeout); 153 wagon.setTimeout(checkTimeout); 154 155 if (wagon instanceof AbstractHttpClientWagon ) { 156 HttpMethodConfiguration httpMethodConfiguration = new HttpMethodConfiguration() // 157 .setUsePreemptive(true) // 158 .setReadTimeout(checkReadTimeout); 159 HttpConfiguration httpConfiguration = new HttpConfiguration().setGet( httpMethodConfiguration); 160 AbstractHttpClientWagon.class.cast(wagon).setHttpConfiguration(httpConfiguration); 161 } 162 163 ProxyInfo proxyInfo = null; 164 if (networkProxy != null) { 165 proxyInfo = new ProxyInfo(); 166 proxyInfo.setType(networkProxy.getProtocol()); 167 proxyInfo.setHost(networkProxy.getHost()); 168 proxyInfo.setPort(networkProxy.getPort()); 169 proxyInfo.setUserName(networkProxy.getUsername()); 170 proxyInfo.setPassword(new String(networkProxy.getPassword())); 171 } 172 String url = StringUtils.stripEnd(remoteRepository.getUrl(), "/"); 173 wagon.connect(new Repository(remoteRepository.getId(), url), proxyInfo); 174 175 // MRM-1933, there are certain servers that do not allow browsing 176 if (!(StringUtils.isEmpty(remoteRepository.getCheckPath()) || 177 "/".equals(remoteRepository.getCheckPath()))) { 178 return wagon.resourceExists(remoteRepository.getCheckPath()); 179 } else { 180 // we only check connectivity as remote repo can be empty 181 // MRM-1909: Wagon implementation appends a slash already 182 wagon.getFileList(""); 183 } 184 185 return Boolean.TRUE; 186 } catch (TransferFailedException e) { 187 log.info("TransferFailedException :{}", e.getMessage()); 188 return Boolean.FALSE; 189 } catch (Exception e) { 190 // This service returns either true or false, Exception cannot be handled by the clients 191 log.debug("Exception occured on connectivity test.", e); 192 log.info("Connection exception: {}", e.getMessage()); 193 return Boolean.FALSE; 194 } 195 196 } 197 198 public int getCheckReadTimeout() { 199 return checkReadTimeout; 200 } 201 202 public void setCheckReadTimeout(int checkReadTimeout) { 203 this.checkReadTimeout = checkReadTimeout; 204 } 205 206 public int getCheckTimeout() { 207 return checkTimeout; 208 } 209 210 public void setCheckTimeout(int checkTimeout) { 211 this.checkTimeout = checkTimeout; 212 } 213 214}