1 package org.apache.archiva.rest.services;
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.admin.model.AuditInformation;
23 import org.apache.archiva.admin.model.RepositoryAdminException;
24 import org.apache.archiva.admin.model.admin.ArchivaAdministration;
25 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
26 import org.apache.archiva.audit.AuditEvent;
27 import org.apache.archiva.audit.AuditListener;
28 import org.apache.archiva.common.utils.VersionUtil;
29 import org.apache.archiva.indexer.search.SearchResultHit;
30 import org.apache.archiva.maven2.model.Artifact;
31 import org.apache.archiva.metadata.model.ArtifactMetadata;
32 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
33 import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
34 import org.apache.archiva.redback.configuration.UserConfiguration;
35 import org.apache.archiva.redback.configuration.UserConfigurationKeys;
36 import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
37 import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
38 import org.apache.archiva.redback.users.User;
39 import org.apache.archiva.repository.RepositoryContentFactory;
40 import org.apache.archiva.repository.RepositoryException;
41 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
42 import org.apache.archiva.rest.services.utils.ArtifactBuilder;
43 import org.apache.archiva.scheduler.repository.DefaultRepositoryArchivaTaskScheduler;
44 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
45 import org.apache.archiva.security.AccessDeniedException;
46 import org.apache.archiva.security.ArchivaSecurityException;
47 import org.apache.archiva.security.PrincipalNotFoundException;
48 import org.apache.archiva.security.UserRepositories;
49 import org.apache.commons.lang.StringUtils;
50 import org.modelmapper.ModelMapper;
51 import org.modelmapper.PropertyMap;
52 import org.modelmapper.convention.MatchingStrategies;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.context.ApplicationContext;
57 import javax.inject.Inject;
58 import javax.inject.Named;
59 import javax.servlet.http.HttpServletRequest;
60 import javax.servlet.http.HttpServletResponse;
61 import javax.ws.rs.core.Context;
62 import javax.ws.rs.core.Response;
63 import java.util.ArrayList;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.List;
70 * abstract class with common utilities methods
72 * @author Olivier Lamy
75 public abstract class AbstractRestService
78 protected Logger log = LoggerFactory.getLogger( getClass() );
81 private List<AuditListener> auditListeners = new ArrayList<>();
84 protected UserRepositories userRepositories;
88 * FIXME: this could be multiple implementations and needs to be configured.
91 @Named(value = "repositorySessionFactory")
92 protected RepositorySessionFactory repositorySessionFactory;
95 protected ArchivaAdministration archivaAdministration;
98 protected ManagedRepositoryAdmin managedRepositoryAdmin;
101 protected RepositoryContentFactory repositoryContentFactory;
104 @Named(value = "archivaTaskScheduler#repository")
105 protected DefaultRepositoryArchivaTaskScheduler repositoryTaskScheduler;
109 @Named(value = "userConfiguration#default")
110 protected UserConfiguration config;
113 protected HttpServletRequest httpServletRequest;
116 protected HttpServletResponse httpServletResponse;
118 protected AuditInformation getAuditInformation()
120 RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
121 User user = redbackRequestInformation == null ? null : redbackRequestInformation.getUser();
122 String remoteAddr = redbackRequestInformation == null ? null : redbackRequestInformation.getRemoteAddr();
123 return new AuditInformation( user, remoteAddr );
126 public List<AuditListener> getAuditListeners()
128 return auditListeners;
131 public void setAuditListeners( List<AuditListener> auditListeners )
133 this.auditListeners = auditListeners;
136 protected List<String> getObservableRepos()
140 List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() );
141 return ids == null ? Collections.<String>emptyList() : ids;
143 catch ( PrincipalNotFoundException e )
145 log.warn( e.getMessage(), e );
147 catch ( AccessDeniedException e )
149 log.warn( e.getMessage(), e );
151 catch ( ArchivaSecurityException e )
153 log.warn( e.getMessage(), e );
155 return Collections.emptyList();
158 protected String getPrincipal()
160 RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
162 return redbackRequestInformation == null
163 ? config.getString( UserConfigurationKeys.DEFAULT_GUEST )
164 : ( redbackRequestInformation.getUser() == null
165 ? config.getString( UserConfigurationKeys.DEFAULT_GUEST )
166 : redbackRequestInformation.getUser().getUsername() );
169 protected String getBaseUrl()
170 throws RepositoryAdminException
172 String applicationUrl = archivaAdministration.getUiConfiguration().getApplicationUrl();
173 if ( StringUtils.isNotBlank( applicationUrl ) )
175 return applicationUrl;
177 return httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + (
178 httpServletRequest.getServerPort() == 80 ? "" : ":" + httpServletRequest.getServerPort() )
179 + httpServletRequest.getContextPath();
182 protected <T> Map<String, T> getBeansOfType( ApplicationContext applicationContext, Class<T> clazz )
184 //TODO do some caching here !!!
185 // olamy : with plexus we get only roleHint
186 // as per convention we named spring bean role#hint remove role# if exists
187 Map<String, T> springBeans = applicationContext.getBeansOfType( clazz );
189 Map<String, T> beans = new HashMap<>( springBeans.size() );
191 for ( Map.Entry<String, T> entry : springBeans.entrySet() )
193 String key = StringUtils.contains( entry.getKey(), '#' )
194 ? StringUtils.substringAfterLast( entry.getKey(), "#" )
196 beans.put( key, entry.getValue() );
201 protected void triggerAuditEvent( String repositoryId, String filePath, String action )
203 AuditEvent auditEvent = new AuditEvent( repositoryId, getPrincipal(), filePath, action );
204 AuditInformation auditInformation = getAuditInformation();
205 auditEvent.setUserId( auditInformation.getUser() == null ? "" : auditInformation.getUser().getUsername() );
206 auditEvent.setRemoteIP( auditInformation.getRemoteAddr() );
207 for ( AuditListener auditListener : getAuditListeners() )
209 auditListener.auditEvent( auditEvent );
217 protected String getArtifactUrl( Artifact artifact )
218 throws ArchivaRestServiceException
220 return getArtifactUrl( artifact, null );
224 protected String getArtifactUrl( Artifact artifact, String repositoryId )
225 throws ArchivaRestServiceException
230 if ( httpServletRequest == null )
235 StringBuilder sb = new StringBuilder( getBaseUrl() );
237 sb.append( "/repository" );
239 // when artifact come from a remote repository when have here the remote repo id
240 // we must replace it with a valid managed one available for the user.
241 if ( StringUtils.isEmpty( repositoryId ) )
243 sb.append( '/' ).append( artifact.getContext() );
247 sb.append( '/' ).append( repositoryId );
250 sb.append( '/' ).append( StringUtils.replaceChars( artifact.getGroupId(), '.', '/' ) );
251 sb.append( '/' ).append( artifact.getArtifactId() );
252 if ( VersionUtil.isSnapshot( artifact.getVersion() ) )
254 sb.append( '/' ).append( VersionUtil.getBaseVersion( artifact.getVersion() ) );
258 sb.append( '/' ).append( artifact.getVersion() );
260 sb.append( '/' ).append( artifact.getArtifactId() );
261 sb.append( '-' ).append( artifact.getVersion() );
262 if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
264 sb.append( '-' ).append( artifact.getClassifier() );
266 // maven-plugin packaging is a jar
267 if ( StringUtils.equals( "maven-plugin", artifact.getPackaging() ) )
273 sb.append( '.' ).append( artifact.getFileExtension() );
276 return sb.toString();
278 catch ( RepositoryAdminException e )
280 throw new ArchivaRestServiceException( e.getMessage(),
281 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
285 protected List<Artifact> buildArtifacts( List<ArtifactMetadata> artifactMetadatas, String repositoryId )
286 throws ArchivaRestServiceException
290 if ( artifactMetadatas != null && !artifactMetadatas.isEmpty() )
292 List<Artifact> artifacts = new ArrayList<>( artifactMetadatas.size() );
293 for ( ArtifactMetadata artifact : artifactMetadatas )
296 ArtifactBuilder builder =
297 new ArtifactBuilder().forArtifactMetadata( artifact ).withManagedRepositoryContent(
298 repositoryContentFactory.getManagedRepositoryContent( repositoryId ) );
299 Artifact art = builder.build();
300 art.setUrl( getArtifactUrl( art ) );
301 artifacts.add( art );
305 return Collections.emptyList();
307 catch ( RepositoryException e )
309 log.error( e.getMessage(), e );
310 throw new ArchivaRestServiceException( e.getMessage(),
311 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
315 protected Boolean doScanRepository( String repositoryId, boolean fullScan )
317 if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
319 log.info( "scanning of repository with id {} already scheduled", repositoryId );
320 return Boolean.FALSE;
322 RepositoryTask task = new RepositoryTask();
323 task.setRepositoryId( repositoryId );
324 task.setScanAll( fullScan );
327 repositoryTaskScheduler.queueTask( task );
329 catch ( TaskQueueException e )
331 log.error( "failed to schedule scanning of repo with id {}", repositoryId, e );
337 private static class ModelMapperHolder
339 private static ModelMapper MODEL_MAPPER = new ModelMapper();
343 MODEL_MAPPER.addMappings( new SearchResultHitMap() );
344 MODEL_MAPPER.getConfiguration().setMatchingStrategy( MatchingStrategies.STRICT );
349 private static class SearchResultHitMap
350 extends PropertyMap<SearchResultHit, Artifact>
353 protected void configure()
355 skip().setId( null );
361 protected ModelMapper getModelMapper()
363 return ModelMapperHolder.MODEL_MAPPER;