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.

DefaultBrowseService.java 53KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359
  1. package org.apache.archiva.rest.services;
  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.beans.ManagedRepository;
  21. import org.apache.archiva.common.utils.VersionComparator;
  22. import org.apache.archiva.common.utils.VersionUtil;
  23. import org.apache.archiva.dependency.tree.maven2.DependencyTreeBuilder;
  24. import org.apache.archiva.maven2.metadata.MavenMetadataReader;
  25. import org.apache.archiva.maven2.model.Artifact;
  26. import org.apache.archiva.maven2.model.TreeEntry;
  27. import org.apache.archiva.metadata.generic.GenericMetadataFacet;
  28. import org.apache.archiva.metadata.model.ArtifactMetadata;
  29. import org.apache.archiva.metadata.model.MetadataFacet;
  30. import org.apache.archiva.metadata.model.ProjectVersionMetadata;
  31. import org.apache.archiva.metadata.model.ProjectVersionReference;
  32. import org.apache.archiva.metadata.repository.*;
  33. import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMetadataVersionComparator;
  34. import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
  35. import org.apache.archiva.model.ArchivaArtifact;
  36. import org.apache.archiva.model.ArchivaRepositoryMetadata;
  37. import org.apache.archiva.proxy.ProxyRegistry;
  38. import org.apache.archiva.proxy.model.RepositoryProxyHandler;
  39. import org.apache.archiva.redback.components.cache.Cache;
  40. import org.apache.archiva.repository.ManagedRepositoryContent;
  41. import org.apache.archiva.repository.ReleaseScheme;
  42. import org.apache.archiva.repository.RepositoryException;
  43. import org.apache.archiva.repository.RepositoryNotFoundException;
  44. import org.apache.archiva.repository.metadata.base.MetadataTools;
  45. import org.apache.archiva.repository.storage.StorageAsset;
  46. import org.apache.archiva.repository.storage.StorageUtil;
  47. import org.apache.archiva.rest.api.model.*;
  48. import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
  49. import org.apache.archiva.rest.api.services.BrowseService;
  50. import org.apache.archiva.rest.services.utils.ArtifactContentEntryComparator;
  51. import org.apache.archiva.security.ArchivaSecurityException;
  52. import org.apache.archiva.xml.XMLException;
  53. import org.apache.commons.collections4.CollectionUtils;
  54. import org.apache.commons.io.IOUtils;
  55. import org.apache.commons.lang3.StringUtils;
  56. import org.springframework.stereotype.Service;
  57. import javax.inject.Inject;
  58. import javax.inject.Named;
  59. import javax.ws.rs.core.Response;
  60. import java.io.IOException;
  61. import java.io.InputStream;
  62. import java.nio.charset.Charset;
  63. import java.nio.file.Files;
  64. import java.util.*;
  65. import java.util.jar.JarEntry;
  66. import java.util.jar.JarFile;
  67. import java.util.zip.ZipEntry;
  68. /**
  69. * @author Olivier Lamy
  70. * @since 1.4-M3
  71. */
  72. @Service( "browseService#rest" )
  73. public class DefaultBrowseService
  74. extends AbstractRestService
  75. implements BrowseService
  76. {
  77. private final Charset ARTIFACT_CONTENT_ENCODING=Charset.forName( "UTF-8" );
  78. @Inject
  79. private DependencyTreeBuilder dependencyTreeBuilder;
  80. @Inject
  81. ProxyRegistry proxyRegistry;
  82. @Inject
  83. @Named( value = "browse#versionMetadata" )
  84. private Cache<String, ProjectVersionMetadata> versionMetadataCache;
  85. private ManagedRepositoryContent getManagedRepositoryContent(String id) throws RepositoryException
  86. {
  87. org.apache.archiva.repository.ManagedRepository repo = repositoryRegistry.getManagedRepository( id );
  88. if (repo==null) {
  89. throw new RepositoryException( "Could not find repository "+id );
  90. }
  91. return repo.getContent();
  92. }
  93. @Override
  94. public BrowseResult getRootGroups( String repositoryId )
  95. throws ArchivaRestServiceException
  96. {
  97. List<String> selectedRepos = getSelectedRepos( repositoryId );
  98. Set<String> namespaces = new LinkedHashSet<String>();
  99. // TODO: this logic should be optional, particularly remembering we want to keep this code simple
  100. // it is located here to avoid the content repository implementation needing to do too much for what
  101. // is essentially presentation code
  102. Set<String> namespacesToCollapse = new LinkedHashSet<String>();
  103. RepositorySession repositorySession = null;
  104. try
  105. {
  106. repositorySession = repositorySessionFactory.createSession();
  107. }
  108. catch ( MetadataRepositoryException e )
  109. {
  110. e.printStackTrace( );
  111. }
  112. try
  113. {
  114. MetadataResolver metadataResolver = repositorySession.getResolver();
  115. for ( String repoId : selectedRepos )
  116. {
  117. namespacesToCollapse.addAll( metadataResolver.resolveRootNamespaces( repositorySession, repoId ) );
  118. }
  119. for ( String n : namespacesToCollapse )
  120. {
  121. // TODO: check performance of this
  122. namespaces.add( collapseNamespaces( repositorySession, metadataResolver, selectedRepos, n ) );
  123. }
  124. }
  125. catch ( MetadataResolutionException e )
  126. {
  127. throw new ArchivaRestServiceException( e.getMessage(),
  128. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  129. }
  130. finally
  131. {
  132. repositorySession.close();
  133. }
  134. List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<>( namespaces.size() );
  135. for ( String namespace : namespaces )
  136. {
  137. browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ) );
  138. }
  139. Collections.sort( browseGroupResultEntries );
  140. return new BrowseResult( browseGroupResultEntries );
  141. }
  142. @Override
  143. public BrowseResult browseGroupId( String groupId, String repositoryId )
  144. throws ArchivaRestServiceException
  145. {
  146. List<String> selectedRepos = getSelectedRepos( repositoryId );
  147. Set<String> projects = new LinkedHashSet<>();
  148. RepositorySession repositorySession = null;
  149. try
  150. {
  151. repositorySession = repositorySessionFactory.createSession();
  152. }
  153. catch ( MetadataRepositoryException e )
  154. {
  155. e.printStackTrace( );
  156. }
  157. Set<String> namespaces;
  158. try
  159. {
  160. MetadataResolver metadataResolver = repositorySession.getResolver();
  161. Set<String> namespacesToCollapse = new LinkedHashSet<>();
  162. for ( String repoId : selectedRepos )
  163. {
  164. namespacesToCollapse.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, groupId ) );
  165. projects.addAll( metadataResolver.resolveProjects( repositorySession, repoId, groupId ) );
  166. }
  167. // TODO: this logic should be optional, particularly remembering we want to keep this code simple
  168. // it is located here to avoid the content repository implementation needing to do too much for what
  169. // is essentially presentation code
  170. namespaces = new LinkedHashSet<>();
  171. for ( String n : namespacesToCollapse )
  172. {
  173. // TODO: check performance of this
  174. namespaces.add(
  175. collapseNamespaces( repositorySession, metadataResolver, selectedRepos, groupId + "." + n ) );
  176. }
  177. }
  178. catch ( MetadataResolutionException e )
  179. {
  180. throw new ArchivaRestServiceException( e.getMessage(),
  181. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  182. }
  183. finally
  184. {
  185. repositorySession.close();
  186. }
  187. List<BrowseResultEntry> browseGroupResultEntries = new ArrayList<>( namespaces.size() + projects.size() );
  188. for ( String namespace : namespaces )
  189. {
  190. browseGroupResultEntries.add( new BrowseResultEntry( namespace, false ).groupId( namespace ) );
  191. }
  192. for ( String project : projects )
  193. {
  194. browseGroupResultEntries.add(
  195. new BrowseResultEntry( groupId + '.' + project, true ).groupId( groupId ).artifactId( project ) );
  196. }
  197. Collections.sort( browseGroupResultEntries );
  198. return new BrowseResult( browseGroupResultEntries );
  199. }
  200. @Override
  201. public VersionsList getVersionsList( String groupId, String artifactId, String repositoryId )
  202. throws ArchivaRestServiceException
  203. {
  204. List<String> selectedRepos = getSelectedRepos( repositoryId );
  205. try
  206. {
  207. Collection<String> versions = getVersions( selectedRepos, groupId, artifactId );
  208. return new VersionsList( new ArrayList<>( versions ) );
  209. }
  210. catch ( MetadataResolutionException e )
  211. {
  212. throw new ArchivaRestServiceException( e.getMessage(),
  213. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  214. }
  215. }
  216. private Collection<String> getVersions( List<String> selectedRepos, String groupId, String artifactId )
  217. throws MetadataResolutionException
  218. {
  219. RepositorySession repositorySession = null;
  220. try
  221. {
  222. repositorySession = repositorySessionFactory.createSession();
  223. }
  224. catch ( MetadataRepositoryException e )
  225. {
  226. e.printStackTrace( );
  227. }
  228. try
  229. {
  230. MetadataResolver metadataResolver = repositorySession.getResolver();
  231. Set<String> versions = new LinkedHashSet<String>();
  232. for ( String repoId : selectedRepos )
  233. {
  234. Collection<String> projectVersions =
  235. metadataResolver.resolveProjectVersions( repositorySession, repoId, groupId, artifactId );
  236. versions.addAll( projectVersions );
  237. }
  238. List<String> sortedVersions = new ArrayList<>( versions );
  239. Collections.sort( sortedVersions, VersionComparator.getInstance() );
  240. return sortedVersions;
  241. }
  242. finally
  243. {
  244. repositorySession.close();
  245. }
  246. }
  247. @Override
  248. public ProjectVersionMetadata getProjectMetadata( String groupId, String artifactId, String version,
  249. String repositoryId )
  250. throws ArchivaRestServiceException
  251. {
  252. List<String> selectedRepos = getSelectedRepos( repositoryId );
  253. RepositorySession repositorySession = null;
  254. try
  255. {
  256. repositorySession = repositorySessionFactory.createSession();
  257. MetadataResolver metadataResolver = repositorySession.getResolver();
  258. ProjectVersionMetadata versionMetadata = null;
  259. for ( String repoId : selectedRepos )
  260. {
  261. if ( versionMetadata == null || versionMetadata.isIncomplete() )
  262. {
  263. try
  264. {
  265. ProjectVersionMetadata versionMetadataTmp =
  266. metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId, artifactId,
  267. version );
  268. if ( versionMetadata == null && versionMetadataTmp != null )
  269. {
  270. versionMetadata = versionMetadataTmp;
  271. }
  272. }
  273. catch ( MetadataResolutionException e )
  274. {
  275. log.warn( "Skipping invalid metadata while compiling shared model for {}:{} in repo {}: {}",
  276. groupId, artifactId, repoId, e.getMessage() );
  277. }
  278. }
  279. }
  280. return versionMetadata;
  281. } catch (MetadataRepositoryException e) {
  282. throw new ArchivaRestServiceException(e.getMessage(), e);
  283. } finally
  284. {
  285. if ( repositorySession != null )
  286. {
  287. repositorySession.close();
  288. }
  289. }
  290. }
  291. @Override
  292. public ProjectVersionMetadata getProjectVersionMetadata( String groupId, String artifactId, String repositoryId )
  293. throws ArchivaRestServiceException
  294. {
  295. List<String> selectedRepos = getSelectedRepos( repositoryId );
  296. RepositorySession repositorySession = null;
  297. try
  298. {
  299. Collection<String> projectVersions = getVersions( selectedRepos, groupId, artifactId );
  300. repositorySession = repositorySessionFactory.createSession();
  301. MetadataResolver metadataResolver = repositorySession.getResolver();
  302. ProjectVersionMetadata sharedModel = new ProjectVersionMetadata();
  303. MavenProjectFacet mavenFacet = new MavenProjectFacet();
  304. mavenFacet.setGroupId( groupId );
  305. mavenFacet.setArtifactId( artifactId );
  306. sharedModel.addFacet( mavenFacet );
  307. boolean isFirstVersion = true;
  308. for ( String version : projectVersions )
  309. {
  310. ProjectVersionMetadata versionMetadata = null;
  311. for ( String repoId : selectedRepos )
  312. {
  313. if ( versionMetadata == null || versionMetadata.isIncomplete() )
  314. {
  315. try
  316. {
  317. ProjectVersionMetadata projectVersionMetadataResolved = null;
  318. boolean useCache = !StringUtils.endsWith( version, VersionUtil.SNAPSHOT );
  319. String cacheKey = null;
  320. boolean cacheToUpdate = false;
  321. // FIXME a bit maven centric!!!
  322. // not a snapshot so get it from cache
  323. if ( useCache )
  324. {
  325. cacheKey = repoId + groupId + artifactId + version;
  326. projectVersionMetadataResolved = versionMetadataCache.get( cacheKey );
  327. }
  328. if ( useCache && projectVersionMetadataResolved != null )
  329. {
  330. versionMetadata = projectVersionMetadataResolved;
  331. }
  332. else
  333. {
  334. projectVersionMetadataResolved =
  335. metadataResolver.resolveProjectVersion( repositorySession, repoId, groupId,
  336. artifactId, version );
  337. versionMetadata = projectVersionMetadataResolved;
  338. cacheToUpdate = true;
  339. }
  340. if ( useCache && cacheToUpdate )
  341. {
  342. versionMetadataCache.put( cacheKey, projectVersionMetadataResolved );
  343. }
  344. }
  345. catch ( MetadataResolutionException e )
  346. {
  347. log.error( "Skipping invalid metadata while compiling shared model for " + groupId + ":"
  348. + artifactId + " in repo " + repoId + ": " + e.getMessage() );
  349. }
  350. }
  351. }
  352. if ( versionMetadata == null )
  353. {
  354. continue;
  355. }
  356. if ( isFirstVersion )
  357. {
  358. sharedModel = versionMetadata;
  359. sharedModel.setId( null );
  360. }
  361. else
  362. {
  363. MavenProjectFacet versionMetadataMavenFacet =
  364. (MavenProjectFacet) versionMetadata.getFacet( MavenProjectFacet.FACET_ID );
  365. if ( versionMetadataMavenFacet != null )
  366. {
  367. if ( mavenFacet.getPackaging() != null //
  368. && !StringUtils.equalsIgnoreCase( mavenFacet.getPackaging(),
  369. versionMetadataMavenFacet.getPackaging() ) )
  370. {
  371. mavenFacet.setPackaging( null );
  372. }
  373. }
  374. if ( StringUtils.isEmpty( sharedModel.getName() ) //
  375. && !StringUtils.isEmpty( versionMetadata.getName() ) )
  376. {
  377. sharedModel.setName( versionMetadata.getName() );
  378. }
  379. if ( sharedModel.getDescription() != null //
  380. && !StringUtils.equalsIgnoreCase( sharedModel.getDescription(),
  381. versionMetadata.getDescription() ) )
  382. {
  383. sharedModel.setDescription( StringUtils.isNotEmpty( versionMetadata.getDescription() )
  384. ? versionMetadata.getDescription()
  385. : "" );
  386. }
  387. if ( sharedModel.getIssueManagement() != null //
  388. && versionMetadata.getIssueManagement() != null //
  389. && !StringUtils.equalsIgnoreCase( sharedModel.getIssueManagement().getUrl(),
  390. versionMetadata.getIssueManagement().getUrl() ) )
  391. {
  392. sharedModel.setIssueManagement( versionMetadata.getIssueManagement() );
  393. }
  394. if ( sharedModel.getCiManagement() != null //
  395. && versionMetadata.getCiManagement() != null //
  396. && !StringUtils.equalsIgnoreCase( sharedModel.getCiManagement().getUrl(),
  397. versionMetadata.getCiManagement().getUrl() ) )
  398. {
  399. sharedModel.setCiManagement( versionMetadata.getCiManagement() );
  400. }
  401. if ( sharedModel.getOrganization() != null //
  402. && versionMetadata.getOrganization() != null //
  403. && !StringUtils.equalsIgnoreCase( sharedModel.getOrganization().getName(),
  404. versionMetadata.getOrganization().getName() ) )
  405. {
  406. sharedModel.setOrganization( versionMetadata.getOrganization() );
  407. }
  408. if ( sharedModel.getUrl() != null //
  409. && !StringUtils.equalsIgnoreCase( sharedModel.getUrl(), versionMetadata.getUrl() ) )
  410. {
  411. sharedModel.setUrl( versionMetadata.getUrl() );
  412. }
  413. }
  414. isFirstVersion = false;
  415. }
  416. return sharedModel;
  417. }
  418. catch (MetadataResolutionException | MetadataRepositoryException e )
  419. {
  420. throw new ArchivaRestServiceException( e.getMessage(),
  421. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  422. }
  423. finally
  424. {
  425. if ( repositorySession != null )
  426. {
  427. repositorySession.close();
  428. }
  429. }
  430. }
  431. @Override
  432. public List<TreeEntry> getTreeEntries( String groupId, String artifactId, String version, String repositoryId )
  433. throws ArchivaRestServiceException
  434. {
  435. List<String> selectedRepos = getSelectedRepos( repositoryId );
  436. try
  437. {
  438. return dependencyTreeBuilder.buildDependencyTree( selectedRepos, groupId, artifactId, version );
  439. }
  440. catch ( Exception e )
  441. {
  442. log.error( e.getMessage(), e );
  443. }
  444. return Collections.emptyList();
  445. }
  446. @Override
  447. public List<ManagedRepository> getUserRepositories()
  448. throws ArchivaRestServiceException
  449. {
  450. try
  451. {
  452. return userRepositories.getAccessibleRepositories( getPrincipal() );
  453. }
  454. catch ( ArchivaSecurityException e )
  455. {
  456. throw new ArchivaRestServiceException( "repositories.read.observable.error",
  457. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  458. }
  459. }
  460. @Override
  461. public List<ManagedRepository> getUserManagableRepositories() throws ArchivaRestServiceException {
  462. try
  463. {
  464. return userRepositories.getManagableRepositories( getPrincipal() );
  465. }
  466. catch ( ArchivaSecurityException e )
  467. {
  468. throw new ArchivaRestServiceException( "repositories.read.managable.error",
  469. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  470. }
  471. }
  472. @Override
  473. public List<Artifact> getDependees( String groupId, String artifactId, String version, String repositoryId )
  474. throws ArchivaRestServiceException
  475. {
  476. List<ProjectVersionReference> references = new ArrayList<>();
  477. // TODO: what if we get duplicates across repositories?
  478. RepositorySession repositorySession = null;
  479. try
  480. {
  481. repositorySession = repositorySessionFactory.createSession();
  482. }
  483. catch ( MetadataRepositoryException e )
  484. {
  485. e.printStackTrace( );
  486. }
  487. try
  488. {
  489. MetadataResolver metadataResolver = repositorySession.getResolver();
  490. for ( String repoId : getObservableRepos() )
  491. {
  492. // TODO: what about if we want to see this irrespective of version?
  493. references.addAll(
  494. metadataResolver.resolveProjectReferences( repositorySession, repoId, groupId, artifactId,
  495. version ) );
  496. }
  497. }
  498. catch ( MetadataResolutionException e )
  499. {
  500. throw new ArchivaRestServiceException( e.getMessage(),
  501. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  502. }
  503. finally
  504. {
  505. repositorySession.close();
  506. }
  507. List<Artifact> artifacts = new ArrayList<>( references.size() );
  508. for ( ProjectVersionReference projectVersionReference : references )
  509. {
  510. artifacts.add( new Artifact( projectVersionReference.getNamespace(), projectVersionReference.getProjectId(),
  511. projectVersionReference.getProjectVersion() ) );
  512. }
  513. return artifacts;
  514. }
  515. @Override
  516. public List<Entry> getMetadatas( String groupId, String artifactId, String version, String repositoryId )
  517. throws ArchivaRestServiceException
  518. {
  519. ProjectVersionMetadata projectVersionMetadata =
  520. getProjectMetadata( groupId, artifactId, version, repositoryId );
  521. if ( projectVersionMetadata == null )
  522. {
  523. return Collections.emptyList();
  524. }
  525. MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
  526. if ( metadataFacet == null )
  527. {
  528. return Collections.emptyList();
  529. }
  530. Map<String, String> map = metadataFacet.toProperties();
  531. List<Entry> entries = new ArrayList<>( map.size() );
  532. for ( Map.Entry<String, String> entry : map.entrySet() )
  533. {
  534. entries.add( new Entry( entry.getKey(), entry.getValue() ) );
  535. }
  536. return entries;
  537. }
  538. @Override
  539. public Boolean addMetadata( String groupId, String artifactId, String version, String key, String value,
  540. String repositoryId )
  541. throws ArchivaRestServiceException
  542. {
  543. ProjectVersionMetadata projectVersionMetadata =
  544. getProjectMetadata( groupId, artifactId, version, repositoryId );
  545. if ( projectVersionMetadata == null )
  546. {
  547. return Boolean.FALSE;
  548. }
  549. Map<String, String> properties = new HashMap<>();
  550. MetadataFacet metadataFacet = projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
  551. if ( metadataFacet != null && metadataFacet.toProperties() != null )
  552. {
  553. properties.putAll( metadataFacet.toProperties() );
  554. }
  555. else
  556. {
  557. metadataFacet = new GenericMetadataFacet();
  558. }
  559. properties.put( key, value );
  560. metadataFacet.fromProperties( properties );
  561. projectVersionMetadata.addFacet( metadataFacet );
  562. RepositorySession repositorySession = null;
  563. try
  564. {
  565. repositorySession = repositorySessionFactory.createSession();
  566. }
  567. catch ( MetadataRepositoryException e )
  568. {
  569. e.printStackTrace( );
  570. }
  571. try
  572. {
  573. MetadataRepository metadataRepository = repositorySession.getRepository();
  574. metadataRepository.updateProjectVersion(repositorySession , repositoryId, groupId, artifactId, projectVersionMetadata );
  575. repositorySession.save();
  576. }
  577. catch (MetadataRepositoryException | MetadataSessionException e )
  578. {
  579. log.error( e.getMessage(), e );
  580. throw new ArchivaRestServiceException( e.getMessage(),
  581. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  582. }
  583. finally
  584. {
  585. repositorySession.close();
  586. }
  587. return Boolean.TRUE;
  588. }
  589. @Override
  590. public Boolean deleteMetadata( String groupId, String artifactId, String version, String key, String repositoryId )
  591. throws ArchivaRestServiceException
  592. {
  593. ProjectVersionMetadata projectVersionMetadata =
  594. getProjectMetadata( groupId, artifactId, version, repositoryId );
  595. if ( projectVersionMetadata == null )
  596. {
  597. return Boolean.FALSE;
  598. }
  599. GenericMetadataFacet metadataFacet =
  600. (GenericMetadataFacet) projectVersionMetadata.getFacet( GenericMetadataFacet.FACET_ID );
  601. if ( metadataFacet != null && metadataFacet.toProperties() != null )
  602. {
  603. Map<String, String> properties = metadataFacet.toProperties();
  604. properties.remove( key );
  605. metadataFacet.setAdditionalProperties( properties );
  606. }
  607. else
  608. {
  609. return Boolean.TRUE;
  610. }
  611. RepositorySession repositorySession = null;
  612. try
  613. {
  614. repositorySession = repositorySessionFactory.createSession();
  615. }
  616. catch ( MetadataRepositoryException e )
  617. {
  618. e.printStackTrace( );
  619. }
  620. try
  621. {
  622. MetadataRepository metadataRepository = repositorySession.getRepository();
  623. metadataRepository.updateProjectVersion(repositorySession , repositoryId, groupId, artifactId, projectVersionMetadata );
  624. repositorySession.save();
  625. }
  626. catch (MetadataRepositoryException | MetadataSessionException e )
  627. {
  628. log.error( e.getMessage(), e );
  629. throw new ArchivaRestServiceException( e.getMessage(),
  630. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  631. }
  632. finally
  633. {
  634. repositorySession.close();
  635. }
  636. return Boolean.TRUE;
  637. }
  638. @Override
  639. public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
  640. String classifier, String type, String path,
  641. String repositoryId )
  642. throws ArchivaRestServiceException
  643. {
  644. List<String> selectedRepos = getSelectedRepos( repositoryId );
  645. try
  646. {
  647. for ( String repoId : selectedRepos )
  648. {
  649. ManagedRepositoryContent managedRepositoryContent =
  650. getManagedRepositoryContent( repoId );
  651. ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
  652. StringUtils.isEmpty( type ) ? "jar" : type,
  653. repoId );
  654. StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
  655. if ( file.exists() )
  656. {
  657. return readFileEntries( file, path, repoId );
  658. }
  659. }
  660. }
  661. catch ( IOException e )
  662. {
  663. log.error( e.getMessage(), e );
  664. throw new ArchivaRestServiceException( e.getMessage(),
  665. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  666. }
  667. catch ( RepositoryNotFoundException e )
  668. {
  669. log.error( e.getMessage(), e );
  670. throw new ArchivaRestServiceException( e.getMessage(),
  671. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  672. }
  673. catch ( RepositoryException e )
  674. {
  675. log.error( e.getMessage(), e );
  676. throw new ArchivaRestServiceException( e.getMessage(),
  677. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  678. }
  679. return Collections.emptyList();
  680. }
  681. @Override
  682. public List<Artifact> getArtifactDownloadInfos( String groupId, String artifactId, String version,
  683. String repositoryId )
  684. throws ArchivaRestServiceException
  685. {
  686. List<String> selectedRepos = getSelectedRepos( repositoryId );
  687. List<Artifact> artifactDownloadInfos = new ArrayList<>();
  688. try (RepositorySession session = repositorySessionFactory.createSession())
  689. {
  690. MetadataResolver metadataResolver = session.getResolver();
  691. for ( String repoId : selectedRepos )
  692. {
  693. List<ArtifactMetadata> artifacts = new ArrayList<>(
  694. metadataResolver.resolveArtifacts( session, repoId, groupId, artifactId, version ) );
  695. Collections.sort( artifacts, ArtifactMetadataVersionComparator.INSTANCE );
  696. if ( artifacts != null && !artifacts.isEmpty() )
  697. {
  698. return buildArtifacts( artifacts, repoId );
  699. }
  700. }
  701. }
  702. catch ( MetadataResolutionException e )
  703. {
  704. log.error( e.getMessage(), e );
  705. throw new ArchivaRestServiceException( e.getMessage(),
  706. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  707. }
  708. catch ( MetadataRepositoryException e )
  709. {
  710. e.printStackTrace( );
  711. }
  712. return artifactDownloadInfos;
  713. }
  714. @Override
  715. public ArtifactContent getArtifactContentText( String groupId, String artifactId, String version, String classifier,
  716. String type, String path, String repositoryId )
  717. throws ArchivaRestServiceException
  718. {
  719. List<String> selectedRepos = getSelectedRepos( repositoryId );
  720. try
  721. {
  722. for ( String repoId : selectedRepos )
  723. {
  724. ManagedRepositoryContent managedRepositoryContent = null;
  725. try
  726. {
  727. managedRepositoryContent = getManagedRepositoryContent( repoId );
  728. }
  729. catch ( RepositoryException e )
  730. {
  731. log.error("No repository content found for "+repoId);
  732. continue;
  733. }
  734. ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
  735. StringUtils.isEmpty( type ) ? "jar" : type,
  736. repoId );
  737. StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
  738. if ( !file.exists() )
  739. {
  740. log.debug( "file: {} not exists for repository: {} try next repository", file, repoId );
  741. continue;
  742. }
  743. if ( StringUtils.isNotBlank( path ) )
  744. {
  745. // zip entry of the path -> path must a real file entry of the archive
  746. StorageUtil.PathInformation pathInfo = StorageUtil.getAssetDataAsPath(file);
  747. JarFile jarFile = new JarFile( pathInfo.getPath().toFile());
  748. ZipEntry zipEntry = jarFile.getEntry( path );
  749. try (InputStream inputStream = jarFile.getInputStream( zipEntry ))
  750. {
  751. return new ArtifactContent( IOUtils.toString( inputStream, ARTIFACT_CONTENT_ENCODING ), repoId );
  752. }
  753. finally
  754. {
  755. closeQuietly( jarFile );
  756. if (pathInfo.isTmpFile()) {
  757. Files.deleteIfExists(pathInfo.getPath());
  758. }
  759. }
  760. }
  761. try(InputStream readStream = file.getReadStream()) {
  762. return new ArtifactContent(IOUtils.toString(readStream, ARTIFACT_CONTENT_ENCODING), repoId);
  763. }
  764. }
  765. }
  766. catch ( IOException e )
  767. {
  768. log.error( e.getMessage(), e );
  769. throw new ArchivaRestServiceException( e.getMessage(),
  770. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  771. }
  772. log.debug( "artifact: {}:{}:{}:{}:{} not found", groupId, artifactId, version, classifier, type );
  773. // 404 ?
  774. return new ArtifactContent();
  775. }
  776. @Override
  777. public Boolean artifactAvailable( String groupId, String artifactId, String version, String classifier,
  778. String repositoryId )
  779. throws ArchivaRestServiceException
  780. {
  781. List<String> selectedRepos = getSelectedRepos( repositoryId );
  782. boolean snapshot = VersionUtil.isSnapshot( version );
  783. try
  784. {
  785. for ( String repoId : selectedRepos )
  786. {
  787. org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository(repoId);
  788. if (!proxyRegistry.hasHandler(managedRepo.getType())) {
  789. throw new RepositoryException( "No proxy handler found for repository type "+managedRepo.getType());
  790. }
  791. RepositoryProxyHandler proxyHandler = proxyRegistry.getHandler(managedRepo.getType()).get(0);
  792. if ( ( snapshot && !managedRepo.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT) ) || ( !snapshot
  793. && managedRepo.getActiveReleaseSchemes().contains(ReleaseScheme.SNAPSHOT) ) )
  794. {
  795. continue;
  796. }
  797. ManagedRepositoryContent managedRepositoryContent = getManagedRepositoryContent( repoId );
  798. // FIXME default to jar which can be wrong for war zip etc....
  799. ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version,
  800. StringUtils.isEmpty( classifier )
  801. ? ""
  802. : classifier, "jar", repoId );
  803. StorageAsset file = managedRepositoryContent.toFile( archivaArtifact );
  804. if ( file != null && file.exists() )
  805. {
  806. return true;
  807. }
  808. // in case of SNAPSHOT we can have timestamped version locally !
  809. if ( StringUtils.endsWith( version, VersionUtil.SNAPSHOT ) )
  810. {
  811. StorageAsset metadataFile = file.getStorage().getAsset(file.getParent().getPath()+"/"+MetadataTools.MAVEN_METADATA );
  812. if ( metadataFile.exists() )
  813. {
  814. try
  815. {
  816. ArchivaRepositoryMetadata archivaRepositoryMetadata =
  817. MavenMetadataReader.read( metadataFile );
  818. int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
  819. String timeStamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
  820. // rebuild file name with timestamped version and build number
  821. String timeStampFileName = new StringBuilder( artifactId ).append( '-' ) //
  822. .append( StringUtils.remove( version, "-" + VersionUtil.SNAPSHOT ) ) //
  823. .append( '-' ).append( timeStamp ) //
  824. .append( '-' ).append( Integer.toString( buildNumber ) ) //
  825. .append( ( StringUtils.isEmpty( classifier ) ? "" : "-" + classifier ) ) //
  826. .append( ".jar" ).toString();
  827. StorageAsset timeStampFile = file.getStorage().getAsset(file.getParent().getPath() + "/" + timeStampFileName );
  828. log.debug( "try to find timestamped snapshot version file: {}", timeStampFile.getPath() );
  829. if ( timeStampFile.exists() )
  830. {
  831. return true;
  832. }
  833. }
  834. catch (XMLException | IOException e )
  835. {
  836. log.warn( "skip fail to find timestamped snapshot file: {}", e.getMessage() );
  837. }
  838. }
  839. }
  840. String path = managedRepositoryContent.toPath( archivaArtifact );
  841. file = proxyHandler.fetchFromProxies( managedRepositoryContent.getRepository(), path );
  842. if ( file != null && file.exists() )
  843. {
  844. // download pom now
  845. String pomPath = StringUtils.substringBeforeLast( path, ".jar" ) + ".pom";
  846. proxyHandler.fetchFromProxies( managedRepositoryContent.getRepository(), pomPath );
  847. return true;
  848. }
  849. }
  850. } catch ( RepositoryException e )
  851. {
  852. log.error( e.getMessage(), e );
  853. throw new ArchivaRestServiceException( e.getMessage(),
  854. Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
  855. }
  856. return false;
  857. }
  858. @Override
  859. public Boolean artifactAvailable( String groupId, String artifactId, String version, String repositoryId )
  860. throws ArchivaRestServiceException
  861. {
  862. return artifactAvailable( groupId, artifactId, version, null, repositoryId );
  863. }
  864. @Override
  865. public List<Artifact> getArtifacts( String repositoryId )
  866. throws ArchivaRestServiceException
  867. {
  868. RepositorySession repositorySession = null;
  869. try
  870. {
  871. repositorySession = repositorySessionFactory.createSession();
  872. }
  873. catch ( MetadataRepositoryException e )
  874. {
  875. e.printStackTrace( );
  876. }
  877. try
  878. {
  879. List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifacts(repositorySession , repositoryId );
  880. return buildArtifacts( artifactMetadatas, repositoryId );
  881. }
  882. catch ( MetadataRepositoryException e )
  883. {
  884. throw new ArchivaRestServiceException( e.getMessage(), e );
  885. }
  886. finally
  887. {
  888. repositorySession.close();
  889. }
  890. }
  891. @Override
  892. public List<Artifact> getArtifactsByProjectVersionMetadata( String key, String value, String repositoryId )
  893. throws ArchivaRestServiceException
  894. {
  895. RepositorySession repositorySession = null;
  896. try
  897. {
  898. repositorySession = repositorySessionFactory.createSession();
  899. }
  900. catch ( MetadataRepositoryException e )
  901. {
  902. e.printStackTrace( );
  903. }
  904. try
  905. {
  906. List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByProjectVersionFacet(repositorySession , key, value, repositoryId );
  907. return buildArtifacts( artifactMetadatas, repositoryId );
  908. }
  909. catch ( MetadataRepositoryException e )
  910. {
  911. throw new ArchivaRestServiceException( e.getMessage(), e );
  912. }
  913. finally
  914. {
  915. repositorySession.close();
  916. }
  917. }
  918. @Override
  919. public List<Artifact> getArtifactsByMetadata( String key, String value, String repositoryId )
  920. throws ArchivaRestServiceException
  921. {
  922. RepositorySession repositorySession = null;
  923. try
  924. {
  925. repositorySession = repositorySessionFactory.createSession();
  926. }
  927. catch ( MetadataRepositoryException e )
  928. {
  929. e.printStackTrace( );
  930. }
  931. try
  932. {
  933. List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByAttribute(repositorySession , key, value, repositoryId );
  934. return buildArtifacts( artifactMetadatas, repositoryId );
  935. }
  936. catch ( MetadataRepositoryException e )
  937. {
  938. throw new ArchivaRestServiceException( e.getMessage(), e );
  939. }
  940. finally
  941. {
  942. repositorySession.close();
  943. }
  944. }
  945. @Override
  946. public List<Artifact> getArtifactsByProperty( String key, String value, String repositoryId )
  947. throws ArchivaRestServiceException
  948. {
  949. RepositorySession repositorySession = null;
  950. try
  951. {
  952. repositorySession = repositorySessionFactory.createSession();
  953. }
  954. catch ( MetadataRepositoryException e )
  955. {
  956. e.printStackTrace( );
  957. }
  958. try
  959. {
  960. List<ArtifactMetadata> artifactMetadatas = repositorySession.getRepository().getArtifactsByProjectVersionAttribute(repositorySession , key, value, repositoryId );
  961. return buildArtifacts( artifactMetadatas, repositoryId );
  962. }
  963. catch ( MetadataRepositoryException e )
  964. {
  965. throw new ArchivaRestServiceException( e.getMessage(), e );
  966. }
  967. finally
  968. {
  969. repositorySession.close();
  970. }
  971. }
  972. @Override
  973. public Boolean importMetadata( MetadataAddRequest metadataAddRequest, String repositoryId )
  974. throws ArchivaRestServiceException
  975. {
  976. boolean result = true;
  977. for ( Map.Entry<String, String> metadata : metadataAddRequest.getMetadatas().entrySet() )
  978. {
  979. result = addMetadata( metadataAddRequest.getGroupId(), metadataAddRequest.getArtifactId(),
  980. metadataAddRequest.getVersion(), metadata.getKey(), metadata.getValue(),
  981. repositoryId );
  982. if ( !result )
  983. {
  984. break;
  985. }
  986. }
  987. return result;
  988. }
  989. @Override
  990. public List<Artifact> searchArtifacts( String text, String repositoryId, Boolean exact )
  991. throws ArchivaRestServiceException
  992. {
  993. try(RepositorySession repositorySession = repositorySessionFactory.createSession())
  994. {
  995. List<ArtifactMetadata> artifactMetadatas =
  996. repositorySession.getRepository().searchArtifacts(repositorySession , repositoryId, text, exact == null ? false : exact );
  997. return buildArtifacts( artifactMetadatas, repositoryId );
  998. }
  999. catch ( MetadataRepositoryException e )
  1000. {
  1001. throw new ArchivaRestServiceException( e.getMessage(), e );
  1002. }
  1003. }
  1004. @Override
  1005. public List<Artifact> searchArtifacts( String key, String text, String repositoryId, Boolean exact )
  1006. throws ArchivaRestServiceException
  1007. {
  1008. RepositorySession repositorySession = null;
  1009. try
  1010. {
  1011. repositorySession = repositorySessionFactory.createSession();
  1012. }
  1013. catch ( MetadataRepositoryException e )
  1014. {
  1015. e.printStackTrace( );
  1016. }
  1017. try
  1018. {
  1019. List<ArtifactMetadata> artifactMetadatas =
  1020. repositorySession.getRepository().searchArtifacts(repositorySession , repositoryId, key, text, exact == null ? false : exact );
  1021. return buildArtifacts( artifactMetadatas, repositoryId );
  1022. }
  1023. catch ( MetadataRepositoryException e )
  1024. {
  1025. throw new ArchivaRestServiceException( e.getMessage(), e );
  1026. }
  1027. finally
  1028. {
  1029. repositorySession.close();
  1030. }
  1031. }
  1032. //---------------------------
  1033. // internals
  1034. //---------------------------
  1035. private void closeQuietly( JarFile jarFile )
  1036. {
  1037. if ( jarFile != null )
  1038. {
  1039. try
  1040. {
  1041. jarFile.close();
  1042. }
  1043. catch ( IOException e )
  1044. {
  1045. log.warn( "ignore error closing jarFile {}", jarFile.getName() );
  1046. }
  1047. }
  1048. }
  1049. protected List<ArtifactContentEntry> readFileEntries(final StorageAsset file, final String filterPath, final String repoId )
  1050. throws IOException
  1051. {
  1052. String cleanedfilterPath = filterPath==null ? "" : (StringUtils.startsWith(filterPath, "/") ?
  1053. StringUtils.substringAfter(filterPath, "/") : filterPath);
  1054. Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<>();
  1055. int filterDepth = StringUtils.countMatches( cleanedfilterPath, "/" );
  1056. if (!StringUtils.endsWith(cleanedfilterPath,"/") && !StringUtils.isEmpty(cleanedfilterPath)) {
  1057. filterDepth++;
  1058. }
  1059. StorageUtil.PathInformation pathInfo = StorageUtil.getAssetDataAsPath(file);
  1060. JarFile jarFile = new JarFile(pathInfo.getPath().toFile());
  1061. try
  1062. {
  1063. Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
  1064. while ( jarEntryEnumeration.hasMoreElements() )
  1065. {
  1066. JarEntry currentEntry = jarEntryEnumeration.nextElement();
  1067. String cleanedEntryName = StringUtils.endsWith( currentEntry.getName(), "/" ) ? //
  1068. StringUtils.substringBeforeLast( currentEntry.getName(), "/" ) : currentEntry.getName();
  1069. String entryRootPath = getRootPath( cleanedEntryName );
  1070. int depth = StringUtils.countMatches( cleanedEntryName, "/" );
  1071. if ( StringUtils.isEmpty( cleanedfilterPath ) //
  1072. && !artifactContentEntryMap.containsKey( entryRootPath ) //
  1073. && depth == filterDepth )
  1074. {
  1075. artifactContentEntryMap.put( entryRootPath,
  1076. new ArtifactContentEntry( entryRootPath, !currentEntry.isDirectory(),
  1077. depth, repoId ) );
  1078. }
  1079. else
  1080. {
  1081. if ( StringUtils.startsWith( cleanedEntryName, cleanedfilterPath ) //
  1082. && ( depth == filterDepth || ( !currentEntry.isDirectory() && depth == filterDepth ) ) )
  1083. {
  1084. artifactContentEntryMap.put( cleanedEntryName, new ArtifactContentEntry( cleanedEntryName,
  1085. !currentEntry.isDirectory(),
  1086. depth, repoId ) );
  1087. }
  1088. }
  1089. }
  1090. if ( StringUtils.isNotEmpty( cleanedfilterPath ) )
  1091. {
  1092. Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap = new HashMap<>();
  1093. for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
  1094. {
  1095. filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
  1096. }
  1097. List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
  1098. if ( sorted == null )
  1099. {
  1100. return Collections.emptyList();
  1101. }
  1102. Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
  1103. return sorted;
  1104. }
  1105. }
  1106. finally
  1107. {
  1108. if ( jarFile != null )
  1109. {
  1110. jarFile.close();
  1111. }
  1112. if (pathInfo.isTmpFile()) {
  1113. Files.deleteIfExists(pathInfo.getPath());
  1114. }
  1115. }
  1116. List<ArtifactContentEntry> sorted = new ArrayList<>( artifactContentEntryMap.values() );
  1117. Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
  1118. return sorted;
  1119. }
  1120. private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
  1121. {
  1122. int smallestDepth = Integer.MAX_VALUE;
  1123. Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<>();
  1124. for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
  1125. {
  1126. ArtifactContentEntry current = entry.getValue();
  1127. if ( current.getDepth() < smallestDepth )
  1128. {
  1129. smallestDepth = current.getDepth();
  1130. }
  1131. List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
  1132. if ( currentList == null )
  1133. {
  1134. currentList = new ArrayList<>();
  1135. currentList.add( current );
  1136. perDepthList.put( current.getDepth(), currentList );
  1137. }
  1138. else
  1139. {
  1140. currentList.add( current );
  1141. }
  1142. }
  1143. return perDepthList.get( smallestDepth );
  1144. }
  1145. /**
  1146. * @param path
  1147. * @return org/apache -&gt; org , org -&gt; org
  1148. */
  1149. private String getRootPath( String path )
  1150. {
  1151. if ( StringUtils.contains( path, '/' ) )
  1152. {
  1153. return StringUtils.substringBefore( path, "/" );
  1154. }
  1155. return path;
  1156. }
  1157. private List<String> getSelectedRepos( String repositoryId )
  1158. throws ArchivaRestServiceException
  1159. {
  1160. List<String> selectedRepos = getObservableRepos();
  1161. if ( CollectionUtils.isEmpty( selectedRepos ) )
  1162. {
  1163. return Collections.emptyList();
  1164. }
  1165. if ( StringUtils.isNotEmpty( repositoryId ) )
  1166. {
  1167. // check user has karma on the repository
  1168. if ( !selectedRepos.contains( repositoryId ) )
  1169. {
  1170. throw new ArchivaRestServiceException( "browse.root.groups.repositoy.denied",
  1171. Response.Status.FORBIDDEN.getStatusCode(), null );
  1172. }
  1173. selectedRepos = Collections.singletonList( repositoryId );
  1174. }
  1175. return selectedRepos;
  1176. }
  1177. private String collapseNamespaces( RepositorySession repositorySession, MetadataResolver metadataResolver,
  1178. Collection<String> repoIds, String n )
  1179. throws MetadataResolutionException
  1180. {
  1181. Set<String> subNamespaces = new LinkedHashSet<String>();
  1182. for ( String repoId : repoIds )
  1183. {
  1184. subNamespaces.addAll( metadataResolver.resolveNamespaces( repositorySession, repoId, n ) );
  1185. }
  1186. if ( subNamespaces.size() != 1 )
  1187. {
  1188. log.debug( "{} is not collapsible as it has sub-namespaces: {}", n, subNamespaces );
  1189. return n;
  1190. }
  1191. else
  1192. {
  1193. for ( String repoId : repoIds )
  1194. {
  1195. Collection<String> projects = metadataResolver.resolveProjects( repositorySession, repoId, n );
  1196. if ( projects != null && !projects.isEmpty() )
  1197. {
  1198. log.debug( "{} is not collapsible as it has projects", n );
  1199. return n;
  1200. }
  1201. }
  1202. return collapseNamespaces( repositorySession, metadataResolver, repoIds,
  1203. n + "." + subNamespaces.iterator().next() );
  1204. }
  1205. }
  1206. public Cache<String, ProjectVersionMetadata> getVersionMetadataCache()
  1207. {
  1208. return versionMetadataCache;
  1209. }
  1210. public void setVersionMetadataCache( Cache<String, ProjectVersionMetadata> versionMetadataCache )
  1211. {
  1212. this.versionMetadataCache = versionMetadataCache;
  1213. }
  1214. }