001 package 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 022 import org.apache.archiva.admin.model.AuditInformation; 023 import org.apache.archiva.admin.model.RepositoryAdminException; 024 import org.apache.archiva.admin.model.admin.ArchivaAdministration; 025 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 026 import org.apache.archiva.audit.AuditEvent; 027 import org.apache.archiva.audit.AuditListener; 028 import org.apache.archiva.common.utils.VersionUtil; 029 import org.apache.archiva.maven2.model.Artifact; 030 import org.apache.archiva.metadata.model.ArtifactMetadata; 031 import org.apache.archiva.metadata.repository.RepositorySessionFactory; 032 import org.apache.archiva.redback.components.taskqueue.TaskQueueException; 033 import org.apache.archiva.redback.configuration.UserConfiguration; 034 import org.apache.archiva.redback.configuration.UserConfigurationKeys; 035 import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; 036 import org.apache.archiva.redback.rest.services.RedbackRequestInformation; 037 import org.apache.archiva.redback.users.User; 038 import org.apache.archiva.repository.RepositoryContentFactory; 039 import org.apache.archiva.repository.RepositoryException; 040 import org.apache.archiva.rest.api.services.ArchivaRestServiceException; 041 import org.apache.archiva.rest.services.utils.ArtifactBuilder; 042 import org.apache.archiva.scheduler.repository.DefaultRepositoryArchivaTaskScheduler; 043 import org.apache.archiva.scheduler.repository.model.RepositoryTask; 044 import org.apache.archiva.security.AccessDeniedException; 045 import org.apache.archiva.security.ArchivaSecurityException; 046 import org.apache.archiva.security.PrincipalNotFoundException; 047 import org.apache.archiva.security.UserRepositories; 048 import org.apache.commons.lang.StringUtils; 049 import org.slf4j.Logger; 050 import org.slf4j.LoggerFactory; 051 import org.springframework.context.ApplicationContext; 052 053 import javax.inject.Inject; 054 import javax.inject.Named; 055 import javax.servlet.http.HttpServletRequest; 056 import javax.ws.rs.core.Context; 057 import javax.ws.rs.core.Response; 058 import java.util.ArrayList; 059 import java.util.Collections; 060 import java.util.HashMap; 061 import java.util.List; 062 import java.util.Map; 063 064 /** 065 * abstract class with common utilities methods 066 * 067 * @author Olivier Lamy 068 * @since 1.4-M1 069 */ 070 public abstract class AbstractRestService 071 { 072 073 protected Logger log = LoggerFactory.getLogger( getClass() ); 074 075 @Inject 076 private List<AuditListener> auditListeners = new ArrayList<AuditListener>(); 077 078 @Inject 079 protected UserRepositories userRepositories; 080 081 082 /** 083 * FIXME: this could be multiple implementations and needs to be configured. 084 */ 085 @Inject 086 @Named(value = "repositorySessionFactory") 087 protected RepositorySessionFactory repositorySessionFactory; 088 089 @Inject 090 protected ArchivaAdministration archivaAdministration; 091 092 @Inject 093 protected ManagedRepositoryAdmin managedRepositoryAdmin; 094 095 @Inject 096 protected RepositoryContentFactory repositoryContentFactory; 097 098 @Inject 099 @Named(value = "archivaTaskScheduler#repository") 100 protected DefaultRepositoryArchivaTaskScheduler repositoryTaskScheduler; 101 102 103 @Inject 104 @Named( value = "userConfiguration#default" ) 105 protected UserConfiguration config; 106 107 @Context 108 protected HttpServletRequest httpServletRequest; 109 110 protected AuditInformation getAuditInformation() 111 { 112 RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get(); 113 User user = redbackRequestInformation == null ? null : redbackRequestInformation.getUser(); 114 String remoteAddr = redbackRequestInformation == null ? null : redbackRequestInformation.getRemoteAddr(); 115 return new AuditInformation( user, remoteAddr ); 116 } 117 118 public List<AuditListener> getAuditListeners() 119 { 120 return auditListeners; 121 } 122 123 public void setAuditListeners( List<AuditListener> auditListeners ) 124 { 125 this.auditListeners = auditListeners; 126 } 127 128 protected List<String> getObservableRepos() 129 { 130 try 131 { 132 List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() ); 133 return ids == null ? Collections.<String>emptyList() : ids; 134 } 135 catch ( PrincipalNotFoundException e ) 136 { 137 log.warn( e.getMessage(), e ); 138 } 139 catch ( AccessDeniedException e ) 140 { 141 log.warn( e.getMessage(), e ); 142 } 143 catch ( ArchivaSecurityException e ) 144 { 145 log.warn( e.getMessage(), e ); 146 } 147 return Collections.emptyList(); 148 } 149 150 protected String getPrincipal() 151 { 152 RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get(); 153 154 return redbackRequestInformation == null 155 ? config.getString( UserConfigurationKeys.DEFAULT_GUEST ) 156 : ( redbackRequestInformation.getUser() == null 157 ? config.getString( UserConfigurationKeys.DEFAULT_GUEST ) 158 : redbackRequestInformation.getUser().getUsername() ); 159 } 160 161 protected String getBaseUrl() 162 throws RepositoryAdminException 163 { 164 String applicationUrl = archivaAdministration.getUiConfiguration().getApplicationUrl(); 165 if ( StringUtils.isNotBlank( applicationUrl ) ) 166 { 167 return applicationUrl; 168 } 169 return httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + ( 170 httpServletRequest.getServerPort() == 80 ? "" : ":" + httpServletRequest.getServerPort() ) 171 + httpServletRequest.getContextPath(); 172 } 173 174 protected <T> Map<String, T> getBeansOfType( ApplicationContext applicationContext, Class<T> clazz ) 175 { 176 //TODO do some caching here !!! 177 // olamy : with plexus we get only roleHint 178 // as per convention we named spring bean role#hint remove role# if exists 179 Map<String, T> springBeans = applicationContext.getBeansOfType( clazz ); 180 181 Map<String, T> beans = new HashMap<String, T>( springBeans.size() ); 182 183 for ( Map.Entry<String, T> entry : springBeans.entrySet() ) 184 { 185 String key = StringUtils.contains( entry.getKey(), '#' ) 186 ? StringUtils.substringAfterLast( entry.getKey(), "#" ) 187 : entry.getKey(); 188 beans.put( key, entry.getValue() ); 189 } 190 return beans; 191 } 192 193 protected void triggerAuditEvent( String repositoryId, String filePath, String action ) 194 { 195 AuditEvent auditEvent = new AuditEvent( repositoryId, getPrincipal(), filePath, action ); 196 AuditInformation auditInformation = getAuditInformation(); 197 auditEvent.setUserId( auditInformation.getUser() == null ? "" : auditInformation.getUser().getUsername() ); 198 auditEvent.setRemoteIP( auditInformation.getRemoteAddr() ); 199 for ( AuditListener auditListener : getAuditListeners() ) 200 { 201 auditListener.auditEvent( auditEvent ); 202 } 203 } 204 205 /** 206 * @param artifact 207 * @return 208 */ 209 protected String getArtifactUrl( Artifact artifact ) 210 throws ArchivaRestServiceException 211 { 212 try 213 { 214 215 if ( httpServletRequest == null ) 216 { 217 return null; 218 } 219 220 StringBuilder sb = new StringBuilder( getBaseUrl() ); 221 222 sb.append( "/repository" ); 223 224 // FIXME when artifact come from a remote repository when have here the remote repo id 225 // we must replace it with a valid managed one available for the user. 226 227 sb.append( '/' ).append( artifact.getContext() ); 228 229 sb.append( '/' ).append( StringUtils.replaceChars( artifact.getGroupId(), '.', '/' ) ); 230 sb.append( '/' ).append( artifact.getArtifactId() ); 231 if ( VersionUtil.isSnapshot( artifact.getVersion() ) ) 232 { 233 sb.append( '/' ).append( VersionUtil.getBaseVersion( artifact.getVersion() ) ); 234 } 235 else 236 { 237 sb.append( '/' ).append( artifact.getVersion() ); 238 } 239 sb.append( '/' ).append( artifact.getArtifactId() ); 240 sb.append( '-' ).append( artifact.getVersion() ); 241 if ( StringUtils.isNotBlank( artifact.getClassifier() ) ) 242 { 243 sb.append( '-' ).append( artifact.getClassifier() ); 244 } 245 // maven-plugin packaging is a jar 246 if ( StringUtils.equals( "maven-plugin", artifact.getPackaging() ) ) 247 { 248 sb.append( "jar" ); 249 } 250 else 251 { 252 sb.append( '.' ).append( artifact.getFileExtension() ); 253 } 254 255 return sb.toString(); 256 } 257 catch ( RepositoryAdminException e ) 258 { 259 throw new ArchivaRestServiceException( e.getMessage(), 260 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 261 } 262 } 263 264 protected List<Artifact> buildArtifacts( List<ArtifactMetadata> artifactMetadatas, String repositoryId ) 265 throws ArchivaRestServiceException 266 { 267 try 268 { 269 if ( artifactMetadatas != null && !artifactMetadatas.isEmpty() ) 270 { 271 List<Artifact> artifacts = new ArrayList<Artifact>( artifactMetadatas.size() ); 272 for ( ArtifactMetadata artifact : artifactMetadatas ) 273 { 274 275 ArtifactBuilder builder = 276 new ArtifactBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent( 277 repositoryContentFactory.getManagedRepositoryContent( repositoryId ) ); 278 Artifact art = builder.build(); 279 art.setUrl( getArtifactUrl( art ) ); 280 artifacts.add( art ); 281 } 282 return artifacts; 283 } 284 return Collections.emptyList(); 285 } 286 catch ( RepositoryException e ) 287 { 288 log.error( e.getMessage(), e ); 289 throw new ArchivaRestServiceException( e.getMessage(), 290 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e ); 291 } 292 } 293 294 protected Boolean doScanRepository( String repositoryId, boolean fullScan ) 295 { 296 if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) ) 297 { 298 log.info( "scanning of repository with id {} already scheduled", repositoryId ); 299 return Boolean.FALSE; 300 } 301 RepositoryTask task = new RepositoryTask(); 302 task.setRepositoryId( repositoryId ); 303 task.setScanAll( fullScan ); 304 try 305 { 306 repositoryTaskScheduler.queueTask( task ); 307 } 308 catch ( TaskQueueException e ) 309 { 310 log.error( "failed to schedule scanning of repo with id {}", repositoryId, e ); 311 return false; 312 } 313 return true; 314 } 315 }