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.

DefaultRepositoryGroupService.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package org.apache.archiva.rest.services.v2;/*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. * Unless required by applicable law or agreed to in writing,
  12. * software distributed under the License is distributed on an
  13. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. * KIND, either express or implied. See the License for the
  15. * specific language governing permissions and limitations
  16. * under the License.
  17. */
  18. /*
  19. * Licensed to the Apache Software Foundation (ASF) under one
  20. * or more contributor license agreements. See the NOTICE file
  21. * distributed with this work for additional information
  22. * regarding copyright ownership. The ASF licenses this file
  23. * to you under the Apache License, Version 2.0 (the
  24. * "License"); you may not use this file except in compliance
  25. * with the License. You may obtain a copy of the License at
  26. *
  27. * http://www.apache.org/licenses/LICENSE-2.0
  28. * Unless required by applicable law or agreed to in writing,
  29. * software distributed under the License is distributed on an
  30. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  31. * KIND, either express or implied. See the License for the
  32. * specific language governing permissions and limitations
  33. * under the License.
  34. */
  35. import org.apache.archiva.components.registry.RegistryException;
  36. import org.apache.archiva.components.rest.model.PagedResult;
  37. import org.apache.archiva.components.rest.util.QueryHelper;
  38. import org.apache.archiva.configuration.Configuration;
  39. import org.apache.archiva.configuration.IndeterminateConfigurationException;
  40. import org.apache.archiva.configuration.RepositoryGroupConfiguration;
  41. import org.apache.archiva.repository.CheckedResult;
  42. import org.apache.archiva.repository.EditableRepositoryGroup;
  43. import org.apache.archiva.repository.RepositoryException;
  44. import org.apache.archiva.repository.RepositoryRegistry;
  45. import org.apache.archiva.repository.base.ConfigurationHandler;
  46. import org.apache.archiva.repository.validation.ValidationError;
  47. import org.apache.archiva.repository.validation.ValidationResponse;
  48. import org.apache.archiva.rest.api.model.v2.MergeConfiguration;
  49. import org.apache.archiva.rest.api.model.v2.RepositoryGroup;
  50. import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
  51. import org.apache.archiva.rest.api.services.v2.ErrorKeys;
  52. import org.apache.archiva.rest.api.services.v2.ErrorMessage;
  53. import org.apache.archiva.rest.api.services.v2.RepositoryGroupService;
  54. import org.apache.archiva.rest.api.services.v2.ValidationException;
  55. import org.apache.commons.lang3.StringUtils;
  56. import org.slf4j.Logger;
  57. import org.slf4j.LoggerFactory;
  58. import org.springframework.stereotype.Service;
  59. import javax.servlet.http.HttpServletResponse;
  60. import javax.ws.rs.core.Context;
  61. import javax.ws.rs.core.Response;
  62. import javax.ws.rs.core.UriInfo;
  63. import java.util.Comparator;
  64. import java.util.List;
  65. import java.util.Map;
  66. import java.util.function.Predicate;
  67. import java.util.stream.Collectors;
  68. /**
  69. * REST V2 Implementation for repository groups.
  70. *
  71. * @author Martin Stockhammer <martin_s@apache.org>
  72. * @see RepositoryGroupService
  73. * @since 3.0
  74. */
  75. @Service("v2.repositoryGroupService#rest")
  76. public class DefaultRepositoryGroupService implements RepositoryGroupService
  77. {
  78. private final ConfigurationHandler configurationHandler;
  79. @Context
  80. HttpServletResponse httpServletResponse;
  81. @Context
  82. UriInfo uriInfo;
  83. final private RepositoryRegistry repositoryRegistry;
  84. private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class );
  85. private static final QueryHelper<org.apache.archiva.repository.RepositoryGroup> QUERY_HELPER = new QueryHelper<>( new String[]{"id"} );
  86. static
  87. {
  88. QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.RepositoryGroup::getId );
  89. QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.RepositoryGroup::getId );
  90. }
  91. public DefaultRepositoryGroupService( RepositoryRegistry repositoryRegistry, ConfigurationHandler configurationHandler ) {
  92. this.repositoryRegistry = repositoryRegistry;
  93. this.configurationHandler = configurationHandler;
  94. }
  95. @Override
  96. public PagedResult<RepositoryGroup> getRepositoriesGroups( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
  97. {
  98. try
  99. {
  100. Predicate<org.apache.archiva.repository.RepositoryGroup> filter = QUERY_HELPER.getQueryFilter( searchTerm );
  101. Comparator<org.apache.archiva.repository.RepositoryGroup> ordering = QUERY_HELPER.getComparator( orderBy, QUERY_HELPER.isAscending( order ) );
  102. int totalCount = Math.toIntExact( repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).count( ) );
  103. List<RepositoryGroup> result = repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).sorted( ordering ).skip( offset ).limit( limit ).map(
  104. RepositoryGroup::of
  105. ).collect( Collectors.toList( ) );
  106. return new PagedResult<>( totalCount, offset, limit, result );
  107. }
  108. catch ( ArithmeticException e )
  109. {
  110. log.error( "Could not convert total count: {}", e.getMessage( ) );
  111. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
  112. }
  113. }
  114. @Override
  115. public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
  116. {
  117. if ( StringUtils.isEmpty( repositoryGroupId ) )
  118. {
  119. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  120. }
  121. org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
  122. return RepositoryGroup.of( group );
  123. }
  124. private RepositoryGroupConfiguration toConfig( RepositoryGroup group )
  125. {
  126. RepositoryGroupConfiguration result = new RepositoryGroupConfiguration( );
  127. result.setId( group.getId( ) );
  128. result.setLocation( group.getLocation( ) );
  129. result.setRepositories( group.getRepositories( ) );
  130. MergeConfiguration mergeConfig = group.getMergeConfiguration( );
  131. if (mergeConfig!=null)
  132. {
  133. result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) );
  134. result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) );
  135. result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) );
  136. }
  137. return result;
  138. }
  139. @Override
  140. public RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
  141. {
  142. final String groupId = repositoryGroup.getId( );
  143. if ( StringUtils.isEmpty( groupId ) ) {
  144. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, groupId ), 422 );
  145. }
  146. if (repositoryRegistry.hasRepositoryGroup( groupId )) {
  147. httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( groupId ).build( ).toString( ) );
  148. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, groupId ), 303 );
  149. }
  150. try
  151. {
  152. RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
  153. CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
  154. if ( validationResult.isValid( ) )
  155. {
  156. httpServletResponse.setStatus( 201 );
  157. return RepositoryGroup.of( validationResult.getRepository() );
  158. } else {
  159. throw ValidationException.of( validationResult.getResult() );
  160. }
  161. }
  162. catch ( RepositoryException e )
  163. {
  164. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) );
  165. }
  166. }
  167. @Override
  168. public RepositoryGroup updateRepositoryGroup( final String repositoryGroupId, final RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException
  169. {
  170. if ( StringUtils.isEmpty( repositoryGroupId ) )
  171. {
  172. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  173. }
  174. if ( !repositoryRegistry.hasRepositoryGroup( repositoryGroupId ) )
  175. {
  176. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 );
  177. }
  178. repositoryGroup.setId( repositoryGroupId );
  179. try
  180. {
  181. RepositoryGroupConfiguration configuration = toConfig( repositoryGroup );
  182. CheckedResult<org.apache.archiva.repository.RepositoryGroup, Map<String, List<ValidationError>>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration );
  183. if ( validationResult.isValid( ) )
  184. {
  185. httpServletResponse.setStatus( 201 );
  186. return RepositoryGroup.of( validationResult.getRepository() );
  187. } else {
  188. throw ValidationException.of( validationResult.getResult() );
  189. }
  190. }
  191. catch ( RepositoryException e )
  192. {
  193. log.error( "Exception during repository group update: {}", e.getMessage( ), e );
  194. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage() ) );
  195. }
  196. }
  197. @Override
  198. public Response deleteRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException
  199. {
  200. if ( StringUtils.isEmpty( repositoryGroupId ) )
  201. {
  202. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  203. }
  204. try
  205. {
  206. org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
  207. if (group==null) {
  208. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  209. }
  210. repositoryRegistry.removeRepositoryGroup( group );
  211. return Response.ok( ).build( );
  212. }
  213. catch ( RepositoryException e )
  214. {
  215. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) );
  216. }
  217. }
  218. @Override
  219. public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, String repositoryId ) throws ArchivaRestServiceException
  220. {
  221. if ( StringUtils.isEmpty( repositoryGroupId ) )
  222. {
  223. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  224. }
  225. if ( StringUtils.isEmpty( repositoryId ) )
  226. {
  227. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
  228. }
  229. try
  230. {
  231. org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
  232. if (repositoryGroup==null) {
  233. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  234. }
  235. if (!(repositoryGroup instanceof EditableRepositoryGroup )) {
  236. log.error( "This group instance is not editable: {}", repositoryGroupId );
  237. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
  238. }
  239. EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
  240. if ( editableRepositoryGroup.getRepositories().stream().anyMatch( repo -> repositoryId.equals(repo.getId())) )
  241. {
  242. log.info( "Repository {} is already member of group {}", repositoryId, repositoryGroupId );
  243. return RepositoryGroup.of( editableRepositoryGroup );
  244. }
  245. org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository(repositoryId);
  246. if (managedRepo==null) {
  247. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 );
  248. }
  249. editableRepositoryGroup.addRepository( managedRepo );
  250. org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
  251. return RepositoryGroup.of( newGroup );
  252. }
  253. catch ( RepositoryException e )
  254. {
  255. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage() ), 500 );
  256. }
  257. }
  258. @Override
  259. public RepositoryGroup deleteRepositoryFromGroup( final String repositoryGroupId, final String repositoryId ) throws org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException
  260. {
  261. if ( StringUtils.isEmpty( repositoryGroupId ) )
  262. {
  263. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, repositoryGroupId ), 404 );
  264. }
  265. if ( StringUtils.isEmpty( repositoryId ) )
  266. {
  267. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
  268. }
  269. try
  270. {
  271. org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId );
  272. if (repositoryGroup==null) {
  273. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 );
  274. }
  275. if (repositoryGroup.getRepositories().stream().noneMatch( r -> repositoryId.equals( r.getId() ) )) {
  276. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
  277. }
  278. if (!(repositoryGroup instanceof EditableRepositoryGroup)) {
  279. log.error( "This group instance is not editable: {}", repositoryGroupId );
  280. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 );
  281. }
  282. EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup;
  283. editableRepositoryGroup.removeRepository( repositoryId );
  284. org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup );
  285. return RepositoryGroup.of( newGroup );
  286. }
  287. catch ( RepositoryException e )
  288. {
  289. throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage() ), 500 );
  290. }
  291. }
  292. }