You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DefaultRepositoryGroupAdmin.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. import org.apache.archiva.admin.model.AuditInformation;
  21. import org.apache.archiva.admin.model.RepositoryAdminException;
  22. import org.apache.archiva.admin.model.beans.ManagedRepository;
  23. import org.apache.archiva.admin.model.beans.RepositoryGroup;
  24. import org.apache.archiva.admin.model.group.RepositoryGroupAdmin;
  25. import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
  26. import org.apache.archiva.admin.repository.AbstractRepositoryAdmin;
  27. import org.apache.archiva.audit.AuditEvent;
  28. import org.apache.archiva.configuration.Configuration;
  29. import org.apache.archiva.configuration.RepositoryGroupConfiguration;
  30. import org.apache.archiva.scheduler.MergedRemoteIndexesScheduler;
  31. import org.apache.commons.lang.StringUtils;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;
  34. import org.springframework.stereotype.Service;
  35. import javax.annotation.PostConstruct;
  36. import javax.inject.Inject;
  37. import java.io.File;
  38. import java.util.ArrayList;
  39. import java.util.Arrays;
  40. import java.util.Collections;
  41. import java.util.HashMap;
  42. import java.util.List;
  43. import java.util.Map;
  44. import java.util.regex.Matcher;
  45. import java.util.regex.Pattern;
  46. /**
  47. * @author Olivier Lamy
  48. */
  49. @Service("repositoryGroupAdmin#default")
  50. public class DefaultRepositoryGroupAdmin
  51. extends AbstractRepositoryAdmin
  52. implements RepositoryGroupAdmin
  53. {
  54. private Logger log = LoggerFactory.getLogger( getClass() );
  55. private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
  56. @Inject
  57. private ManagedRepositoryAdmin managedRepositoryAdmin;
  58. @Inject
  59. private MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
  60. private File groupsDirectory;
  61. @PostConstruct
  62. public void initialize()
  63. {
  64. String appServerBase = getRegistry().getString( "appserver.base" );
  65. groupsDirectory = new File( appServerBase + File.separatorChar + "groups" );
  66. if ( !groupsDirectory.exists() )
  67. {
  68. groupsDirectory.mkdirs();
  69. }
  70. try
  71. {
  72. for ( RepositoryGroup repositoryGroup : getRepositoriesGroups() )
  73. {
  74. mergedRemoteIndexesScheduler.schedule( repositoryGroup,
  75. getMergedIndexDirectory( repositoryGroup.getId() ) );
  76. // create the directory for each group if not exists
  77. File groupPath = new File( groupsDirectory, repositoryGroup.getId() );
  78. if ( !groupPath.exists() )
  79. {
  80. groupPath.mkdirs();
  81. }
  82. }
  83. }
  84. catch ( RepositoryAdminException e )
  85. {
  86. log.warn( "fail to getRepositoriesGroups {}", e.getMessage(), e );
  87. }
  88. }
  89. @Override
  90. public File getMergedIndexDirectory( String repositoryGroupId )
  91. {
  92. return new File( groupsDirectory, repositoryGroupId );
  93. }
  94. public List<RepositoryGroup> getRepositoriesGroups()
  95. throws RepositoryAdminException
  96. {
  97. List<RepositoryGroup> repositoriesGroups =
  98. new ArrayList<>( getArchivaConfiguration().getConfiguration().getRepositoryGroups().size() );
  99. for ( RepositoryGroupConfiguration repositoryGroupConfiguration : getArchivaConfiguration().getConfiguration().getRepositoryGroups() )
  100. {
  101. repositoriesGroups.add( new RepositoryGroup( repositoryGroupConfiguration.getId(), new ArrayList<String>(
  102. repositoryGroupConfiguration.getRepositories() ) ).mergedIndexPath(
  103. repositoryGroupConfiguration.getMergedIndexPath() ).mergedIndexTtl(
  104. repositoryGroupConfiguration.getMergedIndexTtl() ).cronExpression(
  105. repositoryGroupConfiguration.getCronExpression() ) );
  106. }
  107. return repositoriesGroups;
  108. }
  109. public RepositoryGroup getRepositoryGroup( String repositoryGroupId )
  110. throws RepositoryAdminException
  111. {
  112. List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
  113. for ( RepositoryGroup repositoryGroup : repositoriesGroups )
  114. {
  115. if ( StringUtils.equals( repositoryGroupId, repositoryGroup.getId() ) )
  116. {
  117. return repositoryGroup;
  118. }
  119. }
  120. return null;
  121. }
  122. public Boolean addRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
  123. throws RepositoryAdminException
  124. {
  125. validateRepositoryGroup( repositoryGroup, false );
  126. validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
  127. RepositoryGroupConfiguration repositoryGroupConfiguration = new RepositoryGroupConfiguration();
  128. repositoryGroupConfiguration.setId( repositoryGroup.getId() );
  129. repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
  130. repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
  131. repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
  132. repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
  133. Configuration configuration = getArchivaConfiguration().getConfiguration();
  134. configuration.addRepositoryGroup( repositoryGroupConfiguration );
  135. saveConfiguration( configuration );
  136. triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_GROUP, auditInformation );
  137. mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
  138. return Boolean.TRUE;
  139. }
  140. public Boolean deleteRepositoryGroup( String repositoryGroupId, AuditInformation auditInformation )
  141. throws RepositoryAdminException
  142. {
  143. Configuration configuration = getArchivaConfiguration().getConfiguration();
  144. RepositoryGroupConfiguration repositoryGroupConfiguration =
  145. configuration.getRepositoryGroupsAsMap().get( repositoryGroupId );
  146. mergedRemoteIndexesScheduler.unschedule(
  147. new RepositoryGroup( repositoryGroupId, Collections.<String>emptyList() ) );
  148. if ( repositoryGroupConfiguration == null )
  149. {
  150. throw new RepositoryAdminException(
  151. "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot remove" );
  152. }
  153. configuration.removeRepositoryGroup( repositoryGroupConfiguration );
  154. triggerAuditEvent( repositoryGroupId, null, AuditEvent.DELETE_REPO_GROUP, auditInformation );
  155. return Boolean.TRUE;
  156. }
  157. public Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
  158. throws RepositoryAdminException
  159. {
  160. return updateRepositoryGroup( repositoryGroup, auditInformation, true );
  161. }
  162. private Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation,
  163. boolean triggerAuditEvent )
  164. throws RepositoryAdminException
  165. {
  166. validateRepositoryGroup( repositoryGroup, true );
  167. validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
  168. Configuration configuration = getArchivaConfiguration().getConfiguration();
  169. RepositoryGroupConfiguration repositoryGroupConfiguration =
  170. configuration.getRepositoryGroupsAsMap().get( repositoryGroup.getId() );
  171. configuration.removeRepositoryGroup( repositoryGroupConfiguration );
  172. repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
  173. repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
  174. repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
  175. repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
  176. configuration.addRepositoryGroup( repositoryGroupConfiguration );
  177. saveConfiguration( configuration );
  178. if ( triggerAuditEvent )
  179. {
  180. triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.MODIFY_REPO_GROUP, auditInformation );
  181. }
  182. mergedRemoteIndexesScheduler.unschedule( repositoryGroup );
  183. mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
  184. return Boolean.TRUE;
  185. }
  186. public Boolean addRepositoryToGroup( String repositoryGroupId, String repositoryId,
  187. AuditInformation auditInformation )
  188. throws RepositoryAdminException
  189. {
  190. RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
  191. if ( repositoryGroup == null )
  192. {
  193. throw new RepositoryAdminException(
  194. "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot add repository to it" );
  195. }
  196. if ( repositoryGroup.getRepositories().contains( repositoryId ) )
  197. {
  198. throw new RepositoryAdminException(
  199. "repositoryGroup with id " + repositoryGroupId + " already contain repository with id" + repositoryId );
  200. }
  201. validateManagedRepositoriesExists( Arrays.asList( repositoryId ) );
  202. repositoryGroup.addRepository( repositoryId );
  203. updateRepositoryGroup( repositoryGroup, auditInformation, false );
  204. triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_TO_GROUP, auditInformation );
  205. return Boolean.TRUE;
  206. }
  207. public Boolean deleteRepositoryFromGroup( String repositoryGroupId, String repositoryId,
  208. AuditInformation auditInformation )
  209. throws RepositoryAdminException
  210. {
  211. RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
  212. if ( repositoryGroup == null )
  213. {
  214. throw new RepositoryAdminException( "repositoryGroup with id " + repositoryGroupId
  215. + " doesn't not exists so cannot remove repository from it" );
  216. }
  217. if ( !repositoryGroup.getRepositories().contains( repositoryId ) )
  218. {
  219. throw new RepositoryAdminException(
  220. "repositoryGroup with id " + repositoryGroupId + " doesn't not contains repository with id"
  221. + repositoryId
  222. );
  223. }
  224. repositoryGroup.removeRepository( repositoryId );
  225. updateRepositoryGroup( repositoryGroup, auditInformation, false );
  226. triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.DELETE_REPO_FROM_GROUP, auditInformation );
  227. return Boolean.TRUE;
  228. }
  229. public Map<String, RepositoryGroup> getRepositoryGroupsAsMap()
  230. throws RepositoryAdminException
  231. {
  232. List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
  233. Map<String, RepositoryGroup> map = new HashMap<String, RepositoryGroup>( repositoriesGroups.size() );
  234. for ( RepositoryGroup repositoryGroup : repositoriesGroups )
  235. {
  236. map.put( repositoryGroup.getId(), repositoryGroup );
  237. }
  238. return map;
  239. }
  240. public Map<String, List<String>> getGroupToRepositoryMap()
  241. throws RepositoryAdminException
  242. {
  243. java.util.Map<String, java.util.List<String>> map = new java.util.HashMap<String, java.util.List<String>>();
  244. for ( ManagedRepository repo : getManagedRepositoryAdmin().getManagedRepositories() )
  245. {
  246. for ( RepositoryGroup group : getRepositoriesGroups() )
  247. {
  248. if ( !group.getRepositories().contains( repo.getId() ) )
  249. {
  250. String groupId = group.getId();
  251. java.util.List<String> repos = map.get( groupId );
  252. if ( repos == null )
  253. {
  254. repos = new ArrayList<>();
  255. map.put( groupId, repos );
  256. }
  257. repos.add( repo.getId() );
  258. }
  259. }
  260. }
  261. return map;
  262. }
  263. public Map<String, List<String>> getRepositoryToGroupMap()
  264. throws RepositoryAdminException
  265. {
  266. java.util.Map<String, java.util.List<String>> map = new java.util.HashMap<String, java.util.List<String>>();
  267. for ( RepositoryGroup group : getRepositoriesGroups() )
  268. {
  269. for ( String repositoryId : group.getRepositories() )
  270. {
  271. java.util.List<String> groups = map.get( repositoryId );
  272. if ( groups == null )
  273. {
  274. groups = new ArrayList<>();
  275. map.put( repositoryId, groups );
  276. }
  277. groups.add( group.getId() );
  278. }
  279. }
  280. return map;
  281. }
  282. public Boolean validateRepositoryGroup( RepositoryGroup repositoryGroup, boolean updateMode )
  283. throws RepositoryAdminException
  284. {
  285. String repoGroupId = repositoryGroup.getId();
  286. if ( StringUtils.isBlank( repoGroupId ) )
  287. {
  288. throw new RepositoryAdminException( "repositoryGroup id cannot be empty" );
  289. }
  290. if ( repoGroupId.length() > 100 )
  291. {
  292. throw new RepositoryAdminException(
  293. "Identifier [" + repoGroupId + "] is over the maximum limit of 100 characters" );
  294. }
  295. Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
  296. if ( !matcher.matches() )
  297. {
  298. throw new RepositoryAdminException(
  299. "Invalid character(s) found in identifier. Only the following characters are allowed: alphanumeric, '.', '-' and '_'" );
  300. }
  301. if ( repositoryGroup.getMergedIndexTtl() <= 0 )
  302. {
  303. throw new RepositoryAdminException( "Merged Index TTL must be greater than 0." );
  304. }
  305. Configuration configuration = getArchivaConfiguration().getConfiguration();
  306. if ( configuration.getRepositoryGroupsAsMap().containsKey( repoGroupId ) )
  307. {
  308. if ( !updateMode )
  309. {
  310. throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
  311. + "], that id already exists as a repository group." );
  312. }
  313. }
  314. else if ( configuration.getManagedRepositoriesAsMap().containsKey( repoGroupId ) )
  315. {
  316. throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
  317. + "], that id already exists as a managed repository." );
  318. }
  319. else if ( configuration.getRemoteRepositoriesAsMap().containsKey( repoGroupId ) )
  320. {
  321. throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
  322. + "], that id already exists as a remote repository." );
  323. }
  324. return Boolean.TRUE;
  325. }
  326. private void validateManagedRepositoriesExists( List<String> managedRepositoriesIds )
  327. throws RepositoryAdminException
  328. {
  329. for ( String id : managedRepositoriesIds )
  330. {
  331. if ( getManagedRepositoryAdmin().getManagedRepository( id ) == null )
  332. {
  333. throw new RepositoryAdminException(
  334. "managedRepository with id " + id + " not exists so cannot be used in a repositoryGroup" );
  335. }
  336. }
  337. }
  338. public ManagedRepositoryAdmin getManagedRepositoryAdmin()
  339. {
  340. return managedRepositoryAdmin;
  341. }
  342. public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin )
  343. {
  344. this.managedRepositoryAdmin = managedRepositoryAdmin;
  345. }
  346. }