1 package org.apache.archiva.admin.repository.group;
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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
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.ConfigurationEvent;
31 import org.apache.archiva.configuration.ConfigurationListener;
32 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
33 import org.apache.archiva.redback.components.registry.RegistryListener;
34 import org.apache.archiva.scheduler.MergedRemoteIndexesScheduler;
35 import org.apache.commons.lang.StringUtils;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38 import org.springframework.stereotype.Service;
40 import javax.annotation.PostConstruct;
41 import javax.inject.Inject;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.List;
49 import java.util.regex.Matcher;
50 import java.util.regex.Pattern;
53 * @author Olivier Lamy
55 @Service("repositoryGroupAdmin#default")
56 public class DefaultRepositoryGroupAdmin
57 extends AbstractRepositoryAdmin
58 implements RepositoryGroupAdmin
61 private Logger log = LoggerFactory.getLogger( getClass() );
63 private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
66 private ManagedRepositoryAdmin managedRepositoryAdmin;
69 private MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
71 private File groupsDirectory;
74 public void initialize()
76 String appServerBase = getRegistry().getString( "appserver.base" );
77 groupsDirectory = new File( appServerBase + File.separatorChar + "groups" );
78 if ( !groupsDirectory.exists() )
80 groupsDirectory.mkdirs();
85 for ( RepositoryGroup repositoryGroup : getRepositoriesGroups() )
87 mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
90 catch ( RepositoryAdminException e )
92 log.warn( "fail to getRepositoriesGroups {}", e.getMessage(), e );
99 public File getMergedIndexDirectory( String repositoryGroupId )
101 return new File( groupsDirectory, repositoryGroupId );
104 public List<RepositoryGroup> getRepositoriesGroups()
105 throws RepositoryAdminException
107 List<RepositoryGroup> repositoriesGroups =
108 new ArrayList<RepositoryGroup>( getArchivaConfiguration().getConfiguration().getRepositoryGroups().size() );
110 for ( RepositoryGroupConfiguration repositoryGroupConfiguration : getArchivaConfiguration().getConfiguration().getRepositoryGroups() )
112 repositoriesGroups.add( new RepositoryGroup( repositoryGroupConfiguration.getId(), new ArrayList<String>(
113 repositoryGroupConfiguration.getRepositories() ) ).mergedIndexPath(
114 repositoryGroupConfiguration.getMergedIndexPath() ).mergedIndexTtl(
115 repositoryGroupConfiguration.getMergedIndexTtl() ).cronExpression(
116 repositoryGroupConfiguration.getCronExpression() ) );
119 return repositoriesGroups;
122 public RepositoryGroup getRepositoryGroup( String repositoryGroupId )
123 throws RepositoryAdminException
125 List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
126 for ( RepositoryGroup repositoryGroup : repositoriesGroups )
128 if ( StringUtils.equals( repositoryGroupId, repositoryGroup.getId() ) )
130 return repositoryGroup;
136 public Boolean addRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
137 throws RepositoryAdminException
139 validateRepositoryGroup( repositoryGroup, false );
140 validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
142 RepositoryGroupConfiguration repositoryGroupConfiguration = new RepositoryGroupConfiguration();
143 repositoryGroupConfiguration.setId( repositoryGroup.getId() );
144 repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
145 repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
146 repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
147 repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
148 Configuration configuration = getArchivaConfiguration().getConfiguration();
149 configuration.addRepositoryGroup( repositoryGroupConfiguration );
150 saveConfiguration( configuration );
151 triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_GROUP, auditInformation );
152 mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
156 public Boolean deleteRepositoryGroup( String repositoryGroupId, AuditInformation auditInformation )
157 throws RepositoryAdminException
159 Configuration configuration = getArchivaConfiguration().getConfiguration();
160 RepositoryGroupConfiguration repositoryGroupConfiguration =
161 configuration.getRepositoryGroupsAsMap().get( repositoryGroupId );
162 mergedRemoteIndexesScheduler.unschedule(
163 new RepositoryGroup( repositoryGroupId, Collections.<String>emptyList() ) );
164 if ( repositoryGroupConfiguration == null )
166 throw new RepositoryAdminException(
167 "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot remove" );
169 configuration.removeRepositoryGroup( repositoryGroupConfiguration );
170 triggerAuditEvent( repositoryGroupId, null, AuditEvent.DELETE_REPO_GROUP, auditInformation );
175 public Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
176 throws RepositoryAdminException
178 return updateRepositoryGroup( repositoryGroup, auditInformation, true );
181 private Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation,
182 boolean triggerAuditEvent )
183 throws RepositoryAdminException
185 validateRepositoryGroup( repositoryGroup, true );
186 validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
187 Configuration configuration = getArchivaConfiguration().getConfiguration();
189 RepositoryGroupConfiguration repositoryGroupConfiguration =
190 configuration.getRepositoryGroupsAsMap().get( repositoryGroup.getId() );
192 configuration.removeRepositoryGroup( repositoryGroupConfiguration );
194 repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
195 repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
196 repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
197 repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
198 configuration.addRepositoryGroup( repositoryGroupConfiguration );
200 saveConfiguration( configuration );
201 if ( triggerAuditEvent )
203 triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.MODIFY_REPO_GROUP, auditInformation );
205 mergedRemoteIndexesScheduler.unschedule( repositoryGroup );
206 mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
211 public Boolean addRepositoryToGroup( String repositoryGroupId, String repositoryId,
212 AuditInformation auditInformation )
213 throws RepositoryAdminException
215 RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
216 if ( repositoryGroup == null )
218 throw new RepositoryAdminException(
219 "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot add repository to it" );
222 if ( repositoryGroup.getRepositories().contains( repositoryId ) )
224 throw new RepositoryAdminException(
225 "repositoryGroup with id " + repositoryGroupId + " already contain repository with id" + repositoryId );
227 validateManagedRepositoriesExists( Arrays.asList( repositoryId ) );
229 repositoryGroup.addRepository( repositoryId );
230 updateRepositoryGroup( repositoryGroup, auditInformation, false );
231 triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_TO_GROUP, auditInformation );
235 public Boolean deleteRepositoryFromGroup( String repositoryGroupId, String repositoryId,
236 AuditInformation auditInformation )
237 throws RepositoryAdminException
239 RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
240 if ( repositoryGroup == null )
242 throw new RepositoryAdminException( "repositoryGroup with id " + repositoryGroupId
243 + " doesn't not exists so cannot remove repository from it" );
246 if ( !repositoryGroup.getRepositories().contains( repositoryId ) )
248 throw new RepositoryAdminException(
249 "repositoryGroup with id " + repositoryGroupId + " doesn't not contains repository with id"
253 repositoryGroup.removeRepository( repositoryId );
254 updateRepositoryGroup( repositoryGroup, auditInformation, false );
255 triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.DELETE_REPO_FROM_GROUP, auditInformation );
259 public Map<String, RepositoryGroup> getRepositoryGroupsAsMap()
260 throws RepositoryAdminException
262 List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
263 Map<String, RepositoryGroup> map = new HashMap<String, RepositoryGroup>( repositoriesGroups.size() );
264 for ( RepositoryGroup repositoryGroup : repositoriesGroups )
266 map.put( repositoryGroup.getId(), repositoryGroup );
271 public Map<String, List<String>> getGroupToRepositoryMap()
272 throws RepositoryAdminException
275 java.util.Map<String, java.util.List<String>> map = new java.util.HashMap<String, java.util.List<String>>();
277 for ( ManagedRepository repo : getManagedRepositoryAdmin().getManagedRepositories() )
279 for ( RepositoryGroup group : getRepositoriesGroups() )
281 if ( !group.getRepositories().contains( repo.getId() ) )
283 String groupId = group.getId();
284 java.util.List<String> repos = map.get( groupId );
287 repos = new ArrayList<String>();
288 map.put( groupId, repos );
290 repos.add( repo.getId() );
297 public Map<String, List<String>> getRepositoryToGroupMap()
298 throws RepositoryAdminException
300 java.util.Map<String, java.util.List<String>> map = new java.util.HashMap<String, java.util.List<String>>();
302 for ( RepositoryGroup group : getRepositoriesGroups() )
304 for ( String repositoryId : group.getRepositories() )
306 java.util.List<String> groups = map.get( repositoryId );
307 if ( groups == null )
309 groups = new ArrayList<String>();
310 map.put( repositoryId, groups );
312 groups.add( group.getId() );
318 public Boolean validateRepositoryGroup( RepositoryGroup repositoryGroup, boolean updateMode )
319 throws RepositoryAdminException
321 String repoGroupId = repositoryGroup.getId();
322 if ( StringUtils.isBlank( repoGroupId ) )
324 throw new RepositoryAdminException( "repositoryGroup id cannot be empty" );
327 if ( repoGroupId.length() > 100 )
329 throw new RepositoryAdminException(
330 "Identifier [" + repoGroupId + "] is over the maximum limit of 100 characters" );
334 Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
335 if ( !matcher.matches() )
337 throw new RepositoryAdminException(
338 "Invalid character(s) found in identifier. Only the following characters are allowed: alphanumeric, '.', '-' and '_'" );
341 if ( repositoryGroup.getMergedIndexTtl() <= 0 )
343 throw new RepositoryAdminException( "Merged Index TTL must be greater than 0." );
346 Configuration configuration = getArchivaConfiguration().getConfiguration();
348 if ( configuration.getRepositoryGroupsAsMap().containsKey( repoGroupId ) )
352 throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
353 + "], that id already exists as a repository group." );
356 else if ( configuration.getManagedRepositoriesAsMap().containsKey( repoGroupId ) )
358 throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
359 + "], that id already exists as a managed repository." );
361 else if ( configuration.getRemoteRepositoriesAsMap().containsKey( repoGroupId ) )
363 throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
364 + "], that id already exists as a remote repository." );
370 private void validateManagedRepositoriesExists( List<String> managedRepositoriesIds )
371 throws RepositoryAdminException
373 for ( String id : managedRepositoriesIds )
375 if ( getManagedRepositoryAdmin().getManagedRepository( id ) == null )
377 throw new RepositoryAdminException(
378 "managedRepository with id " + id + " not exists so cannot be used in a repositoryGroup" );
383 public ManagedRepositoryAdmin getManagedRepositoryAdmin()
385 return managedRepositoryAdmin;
388 public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin )
390 this.managedRepositoryAdmin = managedRepositoryAdmin;