]> source.dussan.org Git - archiva.git/blob
af4fea009c788ee29314db519b69b9d589640c5a
[archiva.git] /
1 package org.apache.archiva.admin.repository.group;
2 /*
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  */
20
21 import org.apache.archiva.admin.model.AuditInformation;
22 import org.apache.archiva.admin.model.RepositoryAdminException;
23 import org.apache.archiva.admin.model.beans.ManagedRepository;
24 import org.apache.archiva.admin.model.beans.RepositoryGroup;
25 import org.apache.archiva.admin.model.group.RepositoryGroupAdmin;
26 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
27 import org.apache.archiva.admin.repository.AbstractRepositoryAdmin;
28 import org.apache.archiva.audit.AuditEvent;
29 import org.apache.archiva.configuration.Configuration;
30 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
31 import org.apache.archiva.scheduler.MergedRemoteIndexesScheduler;
32 import org.apache.commons.lang.StringUtils;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.stereotype.Service;
36
37 import javax.annotation.PostConstruct;
38 import javax.inject.Inject;
39 import java.io.File;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.regex.Matcher;
47 import java.util.regex.Pattern;
48
49 /**
50  * @author Olivier Lamy
51  */
52 @Service("repositoryGroupAdmin#default")
53 public class DefaultRepositoryGroupAdmin
54     extends AbstractRepositoryAdmin
55     implements RepositoryGroupAdmin
56 {
57
58     private Logger log = LoggerFactory.getLogger( getClass() );
59
60     private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
61
62     @Inject
63     private ManagedRepositoryAdmin managedRepositoryAdmin;
64
65     @Inject
66     private MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
67
68     private File groupsDirectory;
69
70     @PostConstruct
71     public void initialize()
72     {
73         String appServerBase = getRegistry().getString( "appserver.base" );
74         groupsDirectory = new File( appServerBase + File.separatorChar + "groups" );
75         if ( !groupsDirectory.exists() )
76         {
77             groupsDirectory.mkdirs();
78         }
79
80         try
81         {
82             for ( RepositoryGroup repositoryGroup : getRepositoriesGroups() )
83             {
84                 mergedRemoteIndexesScheduler.schedule( repositoryGroup,
85                                                        getMergedIndexDirectory( repositoryGroup.getId() ) );
86                 // create the directory for each group if not exists
87                 File groupPath = new File( groupsDirectory, repositoryGroup.getId() );
88                 if ( !groupPath.exists() )
89                 {
90                     groupPath.mkdirs();
91                 }
92             }
93         }
94         catch ( RepositoryAdminException e )
95         {
96             log.warn( "fail to getRepositoriesGroups {}", e.getMessage(), e );
97         }
98
99     }
100
101
102     @Override
103     public File getMergedIndexDirectory( String repositoryGroupId )
104     {
105         return new File( groupsDirectory, repositoryGroupId );
106     }
107
108     @Override
109     public List<RepositoryGroup> getRepositoriesGroups()
110         throws RepositoryAdminException
111     {
112         List<RepositoryGroup> repositoriesGroups =
113             new ArrayList<>( getArchivaConfiguration().getConfiguration().getRepositoryGroups().size() );
114
115         for ( RepositoryGroupConfiguration repositoryGroupConfiguration : getArchivaConfiguration().getConfiguration().getRepositoryGroups() )
116         {
117             repositoriesGroups.add( new RepositoryGroup( repositoryGroupConfiguration.getId(), new ArrayList<String>(
118                 repositoryGroupConfiguration.getRepositories() ) ).mergedIndexPath(
119                 repositoryGroupConfiguration.getMergedIndexPath() ).mergedIndexTtl(
120                 repositoryGroupConfiguration.getMergedIndexTtl() ).cronExpression(
121                 repositoryGroupConfiguration.getCronExpression() ) );
122         }
123
124         return repositoriesGroups;
125     }
126
127     @Override
128     public RepositoryGroup getRepositoryGroup( String repositoryGroupId )
129         throws RepositoryAdminException
130     {
131         List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
132         for ( RepositoryGroup repositoryGroup : repositoriesGroups )
133         {
134             if ( StringUtils.equals( repositoryGroupId, repositoryGroup.getId() ) )
135             {
136                 return repositoryGroup;
137             }
138         }
139         return null;
140     }
141
142     @Override
143     public Boolean addRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
144         throws RepositoryAdminException
145     {
146         validateRepositoryGroup( repositoryGroup, false );
147         validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
148
149         RepositoryGroupConfiguration repositoryGroupConfiguration = new RepositoryGroupConfiguration();
150         repositoryGroupConfiguration.setId( repositoryGroup.getId() );
151         repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
152         repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
153         repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
154         repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
155         Configuration configuration = getArchivaConfiguration().getConfiguration();
156         configuration.addRepositoryGroup( repositoryGroupConfiguration );
157         saveConfiguration( configuration );
158         triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_GROUP, auditInformation );
159         mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
160         return Boolean.TRUE;
161     }
162
163     @Override
164     public Boolean deleteRepositoryGroup( String repositoryGroupId, AuditInformation auditInformation )
165         throws RepositoryAdminException
166     {
167         Configuration configuration = getArchivaConfiguration().getConfiguration();
168         RepositoryGroupConfiguration repositoryGroupConfiguration =
169             configuration.getRepositoryGroupsAsMap().get( repositoryGroupId );
170         mergedRemoteIndexesScheduler.unschedule(
171             new RepositoryGroup( repositoryGroupId, Collections.<String>emptyList() ) );
172         if ( repositoryGroupConfiguration == null )
173         {
174             throw new RepositoryAdminException(
175                 "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot remove" );
176         }
177         configuration.removeRepositoryGroup( repositoryGroupConfiguration );
178         triggerAuditEvent( repositoryGroupId, null, AuditEvent.DELETE_REPO_GROUP, auditInformation );
179
180         return Boolean.TRUE;
181     }
182
183     @Override
184     public Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
185         throws RepositoryAdminException
186     {
187         return updateRepositoryGroup( repositoryGroup, auditInformation, true );
188     }
189
190     private Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation,
191                                            boolean triggerAuditEvent )
192         throws RepositoryAdminException
193     {
194         validateRepositoryGroup( repositoryGroup, true );
195         validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
196         Configuration configuration = getArchivaConfiguration().getConfiguration();
197
198         RepositoryGroupConfiguration repositoryGroupConfiguration =
199             configuration.getRepositoryGroupsAsMap().get( repositoryGroup.getId() );
200
201         configuration.removeRepositoryGroup( repositoryGroupConfiguration );
202
203         repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
204         repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
205         repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
206         repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
207         configuration.addRepositoryGroup( repositoryGroupConfiguration );
208
209         saveConfiguration( configuration );
210         if ( triggerAuditEvent )
211         {
212             triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.MODIFY_REPO_GROUP, auditInformation );
213         }
214         mergedRemoteIndexesScheduler.unschedule( repositoryGroup );
215         mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
216         return Boolean.TRUE;
217     }
218
219
220     @Override
221     public Boolean addRepositoryToGroup( String repositoryGroupId, String repositoryId,
222                                          AuditInformation auditInformation )
223         throws RepositoryAdminException
224     {
225         RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
226         if ( repositoryGroup == null )
227         {
228             throw new RepositoryAdminException(
229                 "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot add repository to it" );
230         }
231
232         if ( repositoryGroup.getRepositories().contains( repositoryId ) )
233         {
234             throw new RepositoryAdminException(
235                 "repositoryGroup with id " + repositoryGroupId + " already contain repository with id" + repositoryId );
236         }
237         validateManagedRepositoriesExists( Arrays.asList( repositoryId ) );
238
239         repositoryGroup.addRepository( repositoryId );
240         updateRepositoryGroup( repositoryGroup, auditInformation, false );
241         triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_TO_GROUP, auditInformation );
242         return Boolean.TRUE;
243     }
244
245     @Override
246     public Boolean deleteRepositoryFromGroup( String repositoryGroupId, String repositoryId,
247                                               AuditInformation auditInformation )
248         throws RepositoryAdminException
249     {
250         RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
251         if ( repositoryGroup == null )
252         {
253             throw new RepositoryAdminException( "repositoryGroup with id " + repositoryGroupId
254                                                     + " doesn't not exists so cannot remove repository from it" );
255         }
256
257         if ( !repositoryGroup.getRepositories().contains( repositoryId ) )
258         {
259             throw new RepositoryAdminException(
260                 "repositoryGroup with id " + repositoryGroupId + " doesn't not contains repository with id"
261                     + repositoryId
262             );
263         }
264
265         repositoryGroup.removeRepository( repositoryId );
266         updateRepositoryGroup( repositoryGroup, auditInformation, false );
267         triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.DELETE_REPO_FROM_GROUP, auditInformation );
268         return Boolean.TRUE;
269     }
270
271     @Override
272     public Map<String, RepositoryGroup> getRepositoryGroupsAsMap()
273         throws RepositoryAdminException
274     {
275         List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
276         Map<String, RepositoryGroup> map = new HashMap<>( repositoriesGroups.size() );
277         for ( RepositoryGroup repositoryGroup : repositoriesGroups )
278         {
279             map.put( repositoryGroup.getId(), repositoryGroup );
280         }
281         return map;
282     }
283
284     @Override
285     public Map<String, List<String>> getGroupToRepositoryMap()
286         throws RepositoryAdminException
287     {
288
289         Map<String, List<String>> map = new HashMap<>();
290
291         for ( ManagedRepository repo : getManagedRepositoryAdmin().getManagedRepositories() )
292         {
293             for ( RepositoryGroup group : getRepositoriesGroups() )
294             {
295                 if ( !group.getRepositories().contains( repo.getId() ) )
296                 {
297                     String groupId = group.getId();
298                     List<String> repos = map.get( groupId );
299                     if ( repos == null )
300                     {
301                         repos = new ArrayList<>();
302                         map.put( groupId, repos );
303                     }
304                     repos.add( repo.getId() );
305                 }
306             }
307         }
308         return map;
309     }
310
311     @Override
312     public Map<String, List<String>> getRepositoryToGroupMap()
313         throws RepositoryAdminException
314     {
315         Map<String, List<String>> map = new HashMap<>();
316
317         for ( RepositoryGroup group : getRepositoriesGroups() )
318         {
319             for ( String repositoryId : group.getRepositories() )
320             {
321                 List<String> groups = map.get( repositoryId );
322                 if ( groups == null )
323                 {
324                     groups = new ArrayList<>();
325                     map.put( repositoryId, groups );
326                 }
327                 groups.add( group.getId() );
328             }
329         }
330         return map;
331     }
332
333     public Boolean validateRepositoryGroup( RepositoryGroup repositoryGroup, boolean updateMode )
334         throws RepositoryAdminException
335     {
336         String repoGroupId = repositoryGroup.getId();
337         if ( StringUtils.isBlank( repoGroupId ) )
338         {
339             throw new RepositoryAdminException( "repositoryGroup id cannot be empty" );
340         }
341
342         if ( repoGroupId.length() > 100 )
343         {
344             throw new RepositoryAdminException(
345                 "Identifier [" + repoGroupId + "] is over the maximum limit of 100 characters" );
346
347         }
348
349         Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
350         if ( !matcher.matches() )
351         {
352             throw new RepositoryAdminException(
353                 "Invalid character(s) found in identifier. Only the following characters are allowed: alphanumeric, '.', '-' and '_'" );
354         }
355
356         if ( repositoryGroup.getMergedIndexTtl() <= 0 )
357         {
358             throw new RepositoryAdminException( "Merged Index TTL must be greater than 0." );
359         }
360
361         Configuration configuration = getArchivaConfiguration().getConfiguration();
362
363         if ( configuration.getRepositoryGroupsAsMap().containsKey( repoGroupId ) )
364         {
365             if ( !updateMode )
366             {
367                 throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
368                                                         + "], that id already exists as a repository group." );
369             }
370         }
371         else if ( configuration.getManagedRepositoriesAsMap().containsKey( repoGroupId ) )
372         {
373             throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
374                                                     + "], that id already exists as a managed repository." );
375         }
376         else if ( configuration.getRemoteRepositoriesAsMap().containsKey( repoGroupId ) )
377         {
378             throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
379                                                     + "], that id already exists as a remote repository." );
380         }
381
382         return Boolean.TRUE;
383     }
384
385     private void validateManagedRepositoriesExists( List<String> managedRepositoriesIds )
386         throws RepositoryAdminException
387     {
388         for ( String id : managedRepositoriesIds )
389         {
390             if ( getManagedRepositoryAdmin().getManagedRepository( id ) == null )
391             {
392                 throw new RepositoryAdminException(
393                     "managedRepository with id " + id + " not exists so cannot be used in a repositoryGroup" );
394             }
395         }
396     }
397
398     public ManagedRepositoryAdmin getManagedRepositoryAdmin()
399     {
400         return managedRepositoryAdmin;
401     }
402
403     public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin )
404     {
405         this.managedRepositoryAdmin = managedRepositoryAdmin;
406     }
407 }