001package org.apache.archiva.admin.repository.remote; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020 021import org.apache.archiva.admin.model.AuditInformation; 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.admin.repository.AbstractRepositoryAdmin; 026import org.apache.archiva.common.plexusbridge.MavenIndexerUtils; 027import org.apache.archiva.common.plexusbridge.PlexusSisuBridge; 028import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException; 029import org.apache.archiva.configuration.Configuration; 030import org.apache.archiva.configuration.ProxyConnectorConfiguration; 031import org.apache.archiva.configuration.RemoteRepositoryConfiguration; 032import org.apache.archiva.configuration.RepositoryCheckPath; 033import org.apache.archiva.metadata.model.facets.AuditEvent; 034import org.apache.commons.lang.StringUtils; 035import org.apache.maven.index.NexusIndexer; 036import org.apache.maven.index.context.IndexCreator; 037import org.apache.maven.index.context.IndexingContext; 038import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException; 039import org.springframework.stereotype.Service; 040 041import javax.annotation.PostConstruct; 042import javax.annotation.PreDestroy; 043import javax.inject.Inject; 044import java.io.File; 045import java.io.IOException; 046import java.net.MalformedURLException; 047import java.util.ArrayList; 048import java.util.HashMap; 049import java.util.List; 050import java.util.Map; 051 052/** 053 * @author Olivier Lamy 054 * @since 1.4-M1 055 */ 056@Service("remoteRepositoryAdmin#default") 057public class DefaultRemoteRepositoryAdmin 058 extends AbstractRepositoryAdmin 059 implements RemoteRepositoryAdmin 060{ 061 062 @Inject 063 private PlexusSisuBridge plexusSisuBridge; 064 065 @Inject 066 private MavenIndexerUtils mavenIndexerUtils; 067 068 // fields 069 private List<? extends IndexCreator> indexCreators; 070 071 private NexusIndexer indexer; 072 073 @PostConstruct 074 private void initialize() 075 throws RepositoryAdminException 076 { 077 try 078 { 079 indexCreators = mavenIndexerUtils.getAllIndexCreators(); 080 indexer = plexusSisuBridge.lookup( NexusIndexer.class ); 081 } 082 catch ( PlexusSisuBridgeException e ) 083 { 084 throw new RepositoryAdminException( e.getMessage(), e ); 085 } 086 for ( RemoteRepository remoteRepository : getRemoteRepositories() ) 087 { 088 createIndexContext( remoteRepository ); 089 } 090 } 091 092 @PreDestroy 093 private void shutdown() 094 throws RepositoryAdminException 095 { 096 try 097 { 098 List<RemoteRepository> remoteRepositories = getRemoteRepositories(); 099 // close index on shutdown 100 for ( RemoteRepository remoteRepository : remoteRepositories ) 101 { 102 IndexingContext context = indexer.getIndexingContexts().get( remoteRepository.getId() ); 103 if ( context != null ) 104 { 105 indexer.removeIndexingContext( context, false ); 106 } 107 } 108 } 109 catch ( IOException e ) 110 { 111 throw new RepositoryAdminException( e.getMessage(), e ); 112 } 113 } 114 115 116 @Override 117 public List<RemoteRepository> getRemoteRepositories() 118 throws RepositoryAdminException 119 { 120 List<RemoteRepository> remoteRepositories = 121 new ArrayList<>( getArchivaConfiguration().getConfiguration().getRemoteRepositories().size() ); 122 for ( RemoteRepositoryConfiguration repositoryConfiguration : getArchivaConfiguration().getConfiguration().getRemoteRepositories() ) 123 { 124 RemoteRepository remoteRepository = 125 new RemoteRepository( repositoryConfiguration.getId(), repositoryConfiguration.getName(), 126 repositoryConfiguration.getUrl(), repositoryConfiguration.getLayout(), 127 repositoryConfiguration.getUsername(), repositoryConfiguration.getPassword(), 128 repositoryConfiguration.getTimeout() ); 129 remoteRepository.setDownloadRemoteIndex( repositoryConfiguration.isDownloadRemoteIndex() ); 130 remoteRepository.setRemoteIndexUrl( repositoryConfiguration.getRemoteIndexUrl() ); 131 remoteRepository.setCronExpression( repositoryConfiguration.getRefreshCronExpression() ); 132 remoteRepository.setIndexDirectory( repositoryConfiguration.getIndexDir() ); 133 remoteRepository.setRemoteDownloadNetworkProxyId( 134 repositoryConfiguration.getRemoteDownloadNetworkProxyId() ); 135 remoteRepository.setRemoteDownloadTimeout( repositoryConfiguration.getRemoteDownloadTimeout() ); 136 remoteRepository.setDownloadRemoteIndexOnStartup( 137 repositoryConfiguration.isDownloadRemoteIndexOnStartup() ); 138 remoteRepository.setDescription( repositoryConfiguration.getDescription() ); 139 remoteRepository.setExtraHeaders( repositoryConfiguration.getExtraHeaders() ); 140 remoteRepository.setExtraParameters( repositoryConfiguration.getExtraParameters() ); 141 remoteRepository.setCheckPath(repositoryConfiguration.getCheckPath()); 142 remoteRepositories.add( remoteRepository ); 143 } 144 return remoteRepositories; 145 } 146 147 @Override 148 public RemoteRepository getRemoteRepository( String repositoryId ) 149 throws RepositoryAdminException 150 { 151 for ( RemoteRepository remoteRepository : getRemoteRepositories() ) 152 { 153 if ( StringUtils.equals( repositoryId, remoteRepository.getId() ) ) 154 { 155 return remoteRepository; 156 } 157 } 158 return null; 159 } 160 161 @Override 162 public Boolean addRemoteRepository( RemoteRepository remoteRepository, AuditInformation auditInformation ) 163 throws RepositoryAdminException 164 { 165 triggerAuditEvent( remoteRepository.getId(), null, AuditEvent.ADD_REMOTE_REPO, auditInformation ); 166 getRepositoryCommonValidator().basicValidation( remoteRepository, false ); 167 168 //TODO we can validate it's a good uri/url 169 if ( StringUtils.isEmpty( remoteRepository.getUrl() ) ) 170 { 171 throw new RepositoryAdminException( "url cannot be null" ); 172 } 173 174 //MRM-752 - url needs trimming 175 //MRM-1940 - URL should not end with a slash 176 remoteRepository.setUrl( StringUtils.stripEnd(StringUtils.trim( remoteRepository.getUrl() ), "/")); 177 178 if (StringUtils.isEmpty(remoteRepository.getCheckPath())) { 179 String checkUrl = remoteRepository.getUrl().toLowerCase(); 180 for (RepositoryCheckPath path : getArchivaConfiguration ().getConfiguration().getArchivaDefaultConfiguration().getDefaultCheckPaths()) { 181 log.debug("Checking path for urls: {} <-> {}", checkUrl, path.getUrl()); 182 if (checkUrl.startsWith(path.getUrl())) { 183 remoteRepository.setCheckPath(path.getPath()); 184 break; 185 } 186 } 187 } 188 189 RemoteRepositoryConfiguration remoteRepositoryConfiguration = 190 getRemoteRepositoryConfiguration( remoteRepository ); 191 192 Configuration configuration = getArchivaConfiguration().getConfiguration(); 193 configuration.addRemoteRepository( remoteRepositoryConfiguration ); 194 saveConfiguration( configuration ); 195 196 return Boolean.TRUE; 197 } 198 199 @Override 200 public Boolean deleteRemoteRepository( String repositoryId, AuditInformation auditInformation ) 201 throws RepositoryAdminException 202 { 203 204 triggerAuditEvent( repositoryId, null, AuditEvent.DELETE_REMOTE_REPO, auditInformation ); 205 206 Configuration configuration = getArchivaConfiguration().getConfiguration(); 207 208 RemoteRepositoryConfiguration remoteRepositoryConfiguration = 209 configuration.getRemoteRepositoriesAsMap().get( repositoryId ); 210 if ( remoteRepositoryConfiguration == null ) 211 { 212 throw new RepositoryAdminException( 213 "remoteRepository with id " + repositoryId + " not exist cannot remove it" ); 214 } 215 216 configuration.removeRemoteRepository( remoteRepositoryConfiguration ); 217 218 // TODO use ProxyConnectorAdmin interface ? 219 // [MRM-520] Proxy Connectors are not deleted with the deletion of a Repository. 220 List<ProxyConnectorConfiguration> proxyConnectors = new ArrayList<>( configuration.getProxyConnectors() ); 221 for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors ) 222 { 223 if ( StringUtils.equals( proxyConnector.getTargetRepoId(), repositoryId ) ) 224 { 225 configuration.removeProxyConnector( proxyConnector ); 226 } 227 } 228 229 saveConfiguration( configuration ); 230 231 return Boolean.TRUE; 232 } 233 234 @Override 235 public Boolean updateRemoteRepository( RemoteRepository remoteRepository, AuditInformation auditInformation ) 236 throws RepositoryAdminException 237 { 238 239 String repositoryId = remoteRepository.getId(); 240 241 triggerAuditEvent( repositoryId, null, AuditEvent.MODIFY_REMOTE_REPO, auditInformation ); 242 243 // update means : remove and add 244 245 Configuration configuration = getArchivaConfiguration().getConfiguration(); 246 247 RemoteRepositoryConfiguration remoteRepositoryConfiguration = 248 configuration.getRemoteRepositoriesAsMap().get( repositoryId ); 249 if ( remoteRepositoryConfiguration == null ) 250 { 251 throw new RepositoryAdminException( 252 "remoteRepository with id " + repositoryId + " not exist cannot remove it" ); 253 } 254 255 configuration.removeRemoteRepository( remoteRepositoryConfiguration ); 256 257 remoteRepositoryConfiguration = getRemoteRepositoryConfiguration( remoteRepository ); 258 configuration.addRemoteRepository( remoteRepositoryConfiguration ); 259 saveConfiguration( configuration ); 260 261 return Boolean.TRUE; 262 } 263 264 @Override 265 public Map<String, RemoteRepository> getRemoteRepositoriesAsMap() 266 throws RepositoryAdminException 267 { 268 java.util.Map<String, RemoteRepository> map = new HashMap<>(); 269 270 for ( RemoteRepository repo : getRemoteRepositories() ) 271 { 272 map.put( repo.getId(), repo ); 273 } 274 275 return map; 276 } 277 278 @Override 279 public IndexingContext createIndexContext( RemoteRepository remoteRepository ) 280 throws RepositoryAdminException 281 { 282 try 283 { 284 String appServerBase = getRegistry().getString( "appserver.base" ); 285 286 String contextKey = "remote-" + remoteRepository.getId(); 287 IndexingContext indexingContext = indexer.getIndexingContexts().get( contextKey ); 288 if ( indexingContext != null ) 289 { 290 return indexingContext; 291 } 292 // create remote repository path 293 File repoDir = new File( appServerBase, "data/remotes/" + remoteRepository.getId() ); 294 if ( !repoDir.exists() ) 295 { 296 repoDir.mkdirs(); 297 } 298 299 File indexDirectory = null; 300 301 // is there configured indexDirectory ? 302 String indexDirectoryPath = remoteRepository.getIndexDirectory(); 303 304 if ( StringUtils.isNotBlank( indexDirectoryPath ) ) 305 { 306 if ( new File( indexDirectoryPath ).isAbsolute() ) 307 { 308 indexDirectory = new File( indexDirectoryPath ); 309 } 310 else 311 { 312 indexDirectory = new File( repoDir, indexDirectoryPath ); 313 } 314 } 315 // if not configured use a default value 316 if ( indexDirectory == null ) 317 { 318 indexDirectory = new File( repoDir, ".index" ); 319 } 320 if ( !indexDirectory.exists() ) 321 { 322 indexDirectory.mkdirs(); 323 } 324 return indexer.addIndexingContext( contextKey, remoteRepository.getId(), repoDir, indexDirectory, 325 remoteRepository.getUrl(), calculateIndexRemoteUrl( remoteRepository ), 326 mavenIndexerUtils.getAllIndexCreators() ); 327 } 328 catch ( MalformedURLException e ) 329 { 330 throw new RepositoryAdminException( e.getMessage(), e ); 331 } 332 catch ( IOException e ) 333 { 334 throw new RepositoryAdminException( e.getMessage(), e ); 335 } 336 catch ( UnsupportedExistingLuceneIndexException e ) 337 { 338 throw new RepositoryAdminException( e.getMessage(), e ); 339 } 340 341 } 342 343 protected String calculateIndexRemoteUrl( RemoteRepository remoteRepository ) 344 { 345 if ( StringUtils.startsWith( remoteRepository.getRemoteIndexUrl(), "http" ) ) 346 { 347 String baseUrl = remoteRepository.getRemoteIndexUrl(); 348 return baseUrl.endsWith( "/" ) ? StringUtils.substringBeforeLast( baseUrl, "/" ) : baseUrl; 349 } 350 String baseUrl = StringUtils.endsWith( remoteRepository.getUrl(), "/" ) ? StringUtils.substringBeforeLast( 351 remoteRepository.getUrl(), "/" ) : remoteRepository.getUrl(); 352 353 baseUrl = StringUtils.isEmpty( remoteRepository.getRemoteIndexUrl() ) 354 ? baseUrl + "/.index" 355 : baseUrl + "/" + remoteRepository.getRemoteIndexUrl(); 356 return baseUrl; 357 358 } 359 360 private RemoteRepositoryConfiguration getRemoteRepositoryConfiguration( RemoteRepository remoteRepository ) 361 { 362 RemoteRepositoryConfiguration remoteRepositoryConfiguration = new RemoteRepositoryConfiguration(); 363 remoteRepositoryConfiguration.setId( remoteRepository.getId() ); 364 remoteRepositoryConfiguration.setPassword( remoteRepository.getPassword() ); 365 remoteRepositoryConfiguration.setTimeout( remoteRepository.getTimeout() ); 366 remoteRepositoryConfiguration.setUrl( remoteRepository.getUrl() ); 367 remoteRepositoryConfiguration.setUsername( remoteRepository.getUserName() ); 368 remoteRepositoryConfiguration.setLayout( remoteRepository.getLayout() ); 369 remoteRepositoryConfiguration.setName( remoteRepository.getName() ); 370 remoteRepositoryConfiguration.setDownloadRemoteIndex( remoteRepository.isDownloadRemoteIndex() ); 371 remoteRepositoryConfiguration.setRemoteIndexUrl( remoteRepository.getRemoteIndexUrl() ); 372 remoteRepositoryConfiguration.setRefreshCronExpression( remoteRepository.getCronExpression() ); 373 remoteRepositoryConfiguration.setIndexDir( remoteRepository.getIndexDirectory() ); 374 remoteRepositoryConfiguration.setRemoteDownloadNetworkProxyId( 375 remoteRepository.getRemoteDownloadNetworkProxyId() ); 376 remoteRepositoryConfiguration.setRemoteDownloadTimeout( remoteRepository.getRemoteDownloadTimeout() ); 377 remoteRepositoryConfiguration.setDownloadRemoteIndexOnStartup( 378 remoteRepository.isDownloadRemoteIndexOnStartup() ); 379 remoteRepositoryConfiguration.setDescription( remoteRepository.getDescription() ); 380 remoteRepositoryConfiguration.setExtraHeaders( remoteRepository.getExtraHeaders() ); 381 remoteRepositoryConfiguration.setExtraParameters( remoteRepository.getExtraParameters() ); 382 remoteRepositoryConfiguration.setCheckPath(remoteRepository.getCheckPath()); 383 return remoteRepositoryConfiguration; 384 } 385 386}