]> source.dussan.org Git - archiva.git/blob
3443625e581701bb9ea00994a129011b562bad0f
[archiva.git] /
1 package org.apache.archiva.rest.services;
2
3 /*
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
56
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;
67 import java.util.Map;
68
69 /**
70  * abstract class with common utilities methods
71  *
72  * @author Olivier Lamy
73  * @since 1.4-M1
74  */
75 public abstract class AbstractRestService
76 {
77
78     protected Logger log = LoggerFactory.getLogger( getClass() );
79
80     @Inject
81     private List<AuditListener> auditListeners = new ArrayList<>();
82
83     @Inject
84     protected UserRepositories userRepositories;
85
86
87     /**
88      * FIXME: this could be multiple implementations and needs to be configured.
89      */
90     @Inject
91     @Named(value = "repositorySessionFactory")
92     protected RepositorySessionFactory repositorySessionFactory;
93
94     @Inject
95     protected ArchivaAdministration archivaAdministration;
96
97     @Inject
98     protected ManagedRepositoryAdmin managedRepositoryAdmin;
99
100     @Inject
101     protected RepositoryContentFactory repositoryContentFactory;
102
103     @Inject
104     @Named(value = "archivaTaskScheduler#repository")
105     protected DefaultRepositoryArchivaTaskScheduler repositoryTaskScheduler;
106
107
108     @Inject
109     @Named(value = "userConfiguration#default")
110     protected UserConfiguration config;
111
112     @Context
113     protected HttpServletRequest httpServletRequest;
114
115     @Context
116     protected HttpServletResponse httpServletResponse;
117
118     protected AuditInformation getAuditInformation()
119     {
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 );
124     }
125
126     public List<AuditListener> getAuditListeners()
127     {
128         return auditListeners;
129     }
130
131     public void setAuditListeners( List<AuditListener> auditListeners )
132     {
133         this.auditListeners = auditListeners;
134     }
135
136     protected List<String> getObservableRepos()
137     {
138         try
139         {
140             List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() );
141             return ids == null ? Collections.<String>emptyList() : ids;
142         }
143         catch ( PrincipalNotFoundException e )
144         {
145             log.warn( e.getMessage(), e );
146         }
147         catch ( AccessDeniedException e )
148         {
149             log.warn( e.getMessage(), e );
150         }
151         catch ( ArchivaSecurityException e )
152         {
153             log.warn( e.getMessage(), e );
154         }
155         return Collections.emptyList();
156     }
157
158     protected String getPrincipal()
159     {
160         RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
161
162         return redbackRequestInformation == null
163             ? config.getString( UserConfigurationKeys.DEFAULT_GUEST )
164             : ( redbackRequestInformation.getUser() == null
165                 ? config.getString( UserConfigurationKeys.DEFAULT_GUEST )
166                 : redbackRequestInformation.getUser().getUsername() );
167     }
168
169     protected String getBaseUrl()
170         throws RepositoryAdminException
171     {
172         String applicationUrl = archivaAdministration.getUiConfiguration().getApplicationUrl();
173         if ( StringUtils.isNotBlank( applicationUrl ) )
174         {
175             return applicationUrl;
176         }
177         return httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + (
178             httpServletRequest.getServerPort() == 80 ? "" : ":" + httpServletRequest.getServerPort() )
179             + httpServletRequest.getContextPath();
180     }
181
182     protected <T> Map<String, T> getBeansOfType( ApplicationContext applicationContext, Class<T> clazz )
183     {
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 );
188
189         Map<String, T> beans = new HashMap<>( springBeans.size() );
190
191         for ( Map.Entry<String, T> entry : springBeans.entrySet() )
192         {
193             String key = StringUtils.contains( entry.getKey(), '#' )
194                 ? StringUtils.substringAfterLast( entry.getKey(), "#" )
195                 : entry.getKey();
196             beans.put( key, entry.getValue() );
197         }
198         return beans;
199     }
200
201     protected void triggerAuditEvent( String repositoryId, String filePath, String action )
202     {
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() )
208         {
209             auditListener.auditEvent( auditEvent );
210         }
211     }
212
213     /**
214      * @param artifact
215      * @return
216      */
217     protected String getArtifactUrl( Artifact artifact )
218         throws ArchivaRestServiceException
219     {
220         return getArtifactUrl( artifact, null );
221     }
222
223
224     protected String getArtifactUrl( Artifact artifact, String repositoryId )
225         throws ArchivaRestServiceException
226     {
227         try
228         {
229
230             if ( httpServletRequest == null )
231             {
232                 return null;
233             }
234
235             StringBuilder sb = new StringBuilder( getBaseUrl() );
236
237             sb.append( "/repository" );
238
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 ) )
242             {
243                 sb.append( '/' ).append( artifact.getContext() );
244             }
245             else
246             {
247                 sb.append( '/' ).append( repositoryId );
248             }
249
250             sb.append( '/' ).append( StringUtils.replaceChars( artifact.getGroupId(), '.', '/' ) );
251             sb.append( '/' ).append( artifact.getArtifactId() );
252             if ( VersionUtil.isSnapshot( artifact.getVersion() ) )
253             {
254                 sb.append( '/' ).append( VersionUtil.getBaseVersion( artifact.getVersion() ) );
255             }
256             else
257             {
258                 sb.append( '/' ).append( artifact.getVersion() );
259             }
260             sb.append( '/' ).append( artifact.getArtifactId() );
261             sb.append( '-' ).append( artifact.getVersion() );
262             if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
263             {
264                 sb.append( '-' ).append( artifact.getClassifier() );
265             }
266             // maven-plugin packaging is a jar
267             if ( StringUtils.equals( "maven-plugin", artifact.getPackaging() ) )
268             {
269                 sb.append( "jar" );
270             }
271             else
272             {
273                 sb.append( '.' ).append( artifact.getFileExtension() );
274             }
275
276             return sb.toString();
277         }
278         catch ( RepositoryAdminException e )
279         {
280             throw new ArchivaRestServiceException( e.getMessage(),
281                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
282         }
283     }
284
285     protected List<Artifact> buildArtifacts( List<ArtifactMetadata> artifactMetadatas, String repositoryId )
286         throws ArchivaRestServiceException
287     {
288         try
289         {
290             if ( artifactMetadatas != null && !artifactMetadatas.isEmpty() )
291             {
292                 List<Artifact> artifacts = new ArrayList<>( artifactMetadatas.size() );
293                 for ( ArtifactMetadata artifact : artifactMetadatas )
294                 {
295
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 );
302                 }
303                 return artifacts;
304             }
305             return Collections.emptyList();
306         }
307         catch ( RepositoryException e )
308         {
309             log.error( e.getMessage(), e );
310             throw new ArchivaRestServiceException( e.getMessage(),
311                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
312         }
313     }
314
315     protected Boolean doScanRepository( String repositoryId, boolean fullScan )
316     {
317         if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
318         {
319             log.info( "scanning of repository with id {} already scheduled", repositoryId );
320             return Boolean.FALSE;
321         }
322         RepositoryTask task = new RepositoryTask();
323         task.setRepositoryId( repositoryId );
324         task.setScanAll( fullScan );
325         try
326         {
327             repositoryTaskScheduler.queueTask( task );
328         }
329         catch ( TaskQueueException e )
330         {
331             log.error( "failed to schedule scanning of repo with id {}", repositoryId, e );
332             return false;
333         }
334         return true;
335     }
336
337     private static class ModelMapperHolder
338     {
339         private static ModelMapper MODEL_MAPPER = new ModelMapper();
340
341         static
342         {
343             MODEL_MAPPER.addMappings( new SearchResultHitMap() );
344             MODEL_MAPPER.getConfiguration().setMatchingStrategy( MatchingStrategies.STRICT );
345         }
346     }
347
348
349     private static class SearchResultHitMap
350         extends PropertyMap<SearchResultHit, Artifact>
351     {
352         @Override
353         protected void configure()
354         {
355             skip().setId( null );
356         }
357     }
358
359     ;
360
361     protected ModelMapper getModelMapper()
362     {
363         return ModelMapperHolder.MODEL_MAPPER;
364     }
365 }