1 package org.apache.archiva.metadata.repository;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.metadata.QueryParameter;
23 import org.apache.archiva.metadata.model.ArtifactMetadata;
24 import org.apache.archiva.metadata.model.MetadataFacet;
25 import org.apache.archiva.metadata.model.ProjectMetadata;
26 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
27 import org.apache.archiva.metadata.model.ProjectVersionReference;
29 import javax.annotation.Nonnull;
30 import javax.annotation.Nullable;
31 import java.time.ZonedDateTime;
32 import java.util.Collection;
33 import java.util.List;
34 import java.util.stream.Stream;
37 * A Metadata repository provides information about artifact metadata. It does not provide the artifact data itself.
38 * It may be possible to use the same backend for metadata and storage, but this depends on the backends and they are
39 * provided by different APIs.
41 * The motivation for this API is to provide fast access to the repository metadata and fulltext search. Also dependencies
42 * are stored in this repository.
44 * The methods here do not update the artifacts itself. They are only updating the data in the metadata repository.
45 * That means, if you want to update some artifact, you should make sure to update the artifact itself and the metadata
46 * repository (either directly or by repository scanning).
48 * Currently we are providing JCR, File based and Cassandra as backend for the metadata.
50 * The metadata repository uses sessions for accessing the data. Please make sure to always close the sessions after using it.
51 * Best idiom for using the sessions:
53 * try(RepositorySession session = sessionFactory.createSession() {
58 * It is implementation dependent, if the sessions are really used by the backend. E.g. the file based implementation ignores
59 * the sessions completely.
61 * Sessions should be closed immediately after usage. If it is expensive to open a session for a given backend. The backend
62 * should provide a session pool if possible. There are methods for refreshing a session if needed.
64 * You should avoid stacking sessions, that means, do not create a new session in the same thread, when a session is opened already.
66 * Some backend implementations (JCR) update the metadata in the background, that means update of the metadata is not reflected
69 * The base metadata coordinates are:
71 * <li>Repository ID: The identifier of the repository, where the artifact resides</li>
72 * <li>Namespace: This is a hierarchical coordinate for locating the projects. E.g. this corresponds to the groupId in maven. </li>
73 * <li>Project ID: The project itself</li>
74 * <li>Version: Each project may have different versions.</li>
75 * <li>Artifact: Artifacts correspond to files / blob data. Each artifact has additional metadata, like name, version, modification time, ...</li>
78 * As the repository connects to some backend either locally or remote, the access to the repository may fail. The methods capsule the
79 * backend errors into <code>{@link MetadataRepositoryException}</code>.
81 * Facets are the way to provide additional metadata that is not part of the base API. It depends on the repository type (e.g. Maven, NPM,
82 * not the metadata backend) what facets are stored in addition to the standard metadata.
83 * Facets have a specific facet ID that represents the schema for the data stored. For creating specific objects for a given
84 * facet id the <code>{@link org.apache.archiva.metadata.model.MetadataFacetFactory}</code> is used.
85 * For each facet id there may exist multiple facet instances on each level. Facet instances are identified by their name, which may be
86 * a hierarchical path.
87 * The data in each facet instance is stored in properties (key-value pairs). The properties are converted into / from the specific
90 * Facets can be stored on repository, project, version and artifact level.
92 * For retrieving artifacts there are methods that return lists and streaming based methods. Some implementations (e.g. JCR) use
93 * lazy loading for the retrieved objects. So the streaming methods may be faster and use less memory than the list based methods.
94 * But for some backends there is no difference.
97 public interface MetadataRepository
103 * Update metadata for a particular project in the metadata repository, or create it, if it does not already exist.
105 * @param session The session used for updating.
106 * @param repositoryId the repository the project is in
107 * @param project the project metadata to create or update
108 * @throws MetadataRepositoryException if the update fails
110 void updateProject( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull ProjectMetadata project )
111 throws MetadataRepositoryException;
114 * Update the metadata of a given artifact. If the artifact, namespace, version, project does not exist in the repository it will be created.
116 * @param session The repository session
117 * @param repositoryId The repository id
118 * @param namespace The namespace ('.' separated)
119 * @param projectId The project id
120 * @param projectVersion The project version
121 * @param artifactMeta Information about the artifact itself.
122 * @throws MetadataRepositoryException if something goes wrong during update.
124 void updateArtifact( @Nonnull RepositorySession session, @Nonnull String repositoryId,
125 @Nonnull String namespace, @Nonnull String projectId, @Nonnull String projectVersion,
126 @Nonnull ArtifactMetadata artifactMeta )
127 throws MetadataRepositoryException;
130 * Updates the metadata for a specific version of a given project. If the namespace, project, version does not exist,
131 * it will be created.
133 * @param session The repository session
134 * @param repositoryId The repository id
135 * @param namespace The namespace ('.' separated)
136 * @param projectId The project id
137 * @param versionMetadata The metadata for the version
138 * @throws MetadataRepositoryException if something goes wrong during update
140 void updateProjectVersion( @Nonnull RepositorySession session, @Nonnull String repositoryId,
141 @Nonnull String namespace, @Nonnull String projectId,
142 @Nonnull ProjectVersionMetadata versionMetadata )
143 throws MetadataRepositoryException;
146 * Create the namespace in the repository, if it does not exist.
147 * Namespaces do not have specific metadata attached.
149 * @param session The repository session
150 * @param repositoryId The repository id
151 * @param namespace The namespace ('.' separated)
152 * @throws MetadataRepositoryException if something goes wrong during update
154 void updateNamespace( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String namespace )
155 throws MetadataRepositoryException;
158 * Return the facet names stored for the given facet id on the repository level.
160 * @param session The repository session
161 * @param repositoryId The repository id
162 * @param facetId The facet id
163 * @return The list of facet names, or an empty list, if there are no facets stored on this repository for the given facet id.
164 * @throws MetadataRepositoryException if something goes wrong
166 List<String> getMetadataFacets( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String facetId )
167 throws MetadataRepositoryException;
173 * @see #getMetadataFacetStream(RepositorySession, String, Class, QueryParameter queryParameter)
174 * but uses default query parameters.
176 * There is no limitation of the number of result objects returned, but implementations may have a hard upper bound for
177 * the number of results.
180 * @param repositoryId
184 * @throws MetadataRepositoryException
187 <T extends MetadataFacet> Stream<T> getMetadataFacetStream( @Nonnull RepositorySession session,
188 @Nonnull String repositoryId, @Nonnull Class<T> facetClazz)
189 throws MetadataRepositoryException;
192 * Returns a stream of MetadataFacet elements that match the given facet class.
193 * Implementations should order the resulting stream by facet name.
196 * @param session The repository session
197 * @param repositoryId The repository id
198 * @param facetClazz The class of the facet
199 * @param <T> The facet type
201 * @throws MetadataRepositoryException
204 <T extends MetadataFacet> Stream<T> getMetadataFacetStream(@Nonnull RepositorySession session,
205 @Nonnull String repositoryId, @Nonnull Class<T> facetClazz,
206 @Nonnull QueryParameter queryParameter)
207 throws MetadataRepositoryException;
210 * Returns true, if there is facet data stored for the given facet id on the repository on repository level. The facet data itself
211 * may be empty. It's just checking if there is an object stored for the given facet id.
213 * @param session The repository session
214 * @param repositoryId The repository id
215 * @param facetId The facet id
216 * @return true if there is data stored this facetId on repository level.
217 * @throws MetadataRepositoryException if something goes wrong
220 boolean hasMetadataFacet( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String facetId )
221 throws MetadataRepositoryException;
224 * Returns the facet data stored on the repository level. The facet instance is identified by the facet id and the
225 * facet name. The returned object is a instance created by using <code>{@link org.apache.archiva.metadata.model.MetadataFacetFactory}</code>.
227 * @param session The repository session
228 * @param repositoryId The repository id
229 * @param facetId The facet id
230 * @param name The attribute name
231 * @return The facet values
232 * @throws MetadataRepositoryException if something goes wrong.
234 MetadataFacet getMetadataFacet( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String facetId,
235 @Nonnull String name )
236 throws MetadataRepositoryException;
239 * Returns the facet instance for the given class, which is stored on repository level for the given name.
240 * If the given name does not point to a instance that can be represented by this class, <code>null</code> will be returned.
241 * If the facet is not found the method returns <code>null</code>.
243 * @param session The repository session
244 * @param repositoryId The id of the repository
245 * @param clazz The facet object class
246 * @param name The name of the facet (name or path)
247 * @param <T> The type of the facet object
248 * @return The facet instance, if it exists.
249 * @throws MetadataRepositoryException if the data cannot be retrieved from the backend
252 <T extends MetadataFacet> T getMetadataFacet(@Nonnull RepositorySession session, @Nonnull String repositoryId,
253 @Nonnull Class<T> clazz, @Nonnull String name)
254 throws MetadataRepositoryException;
257 * Adds a facet to the repository level.
259 * @param session The repository session
260 * @param repositoryId The id of the repository
261 * @param metadataFacet The facet to add
262 * @throws MetadataRepositoryException if the facet cannot be stored.
264 void addMetadataFacet( @Nonnull RepositorySession session, @Nonnull String repositoryId,
265 @Nonnull MetadataFacet metadataFacet )
266 throws MetadataRepositoryException;
269 * Removes all facets with the given facetId from the repository level.
271 * @param session The repository session
272 * @param repositoryId The id of the repository
273 * @param facetId The facet id
274 * @throws MetadataRepositoryException if the removal fails
276 void removeMetadataFacets( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String facetId )
277 throws MetadataRepositoryException;
280 * Removes the given facet from the repository level, if it exists.
282 * @param session The repository session
283 * @param repositoryId The id of the repository
284 * @param facetId The facet id
285 * @param name The facet name or path
287 void removeMetadataFacet( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String facetId, @Nonnull String name )
288 throws MetadataRepositoryException;
292 * Is the same as {@link #getArtifactsByDateRange(RepositorySession, String, ZonedDateTime, ZonedDateTime, QueryParameter)}, but
293 * uses default query parameters.
296 List<ArtifactMetadata> getArtifactsByDateRange( @Nonnull RepositorySession session, @Nonnull String repositoryId,
297 @Nullable ZonedDateTime startTime, @Nullable ZonedDateTime endTime )
298 throws MetadataRepositoryException;
302 * Searches for artifacts where the 'whenGathered' attribute value is between the given start and end time.
303 * If start or end time or both are <code>null</code>, the time range for the search is unbounded for this parameter.
306 * @param session The repository session
307 * @param repositoryId The repository id
308 * @param startTime The start time/date as zoned date, can be <code>null</code>
309 * @param endTime The end time/date as zoned date, can be <code>null</code>
310 * @param queryParameter Additional parameters for the query that affect ordering and returned results
311 * @return The list of metadata objects for the found instances.
312 * @throws MetadataRepositoryException if the query fails.
315 List<ArtifactMetadata> getArtifactsByDateRange(@Nonnull RepositorySession session, @Nonnull String repositoryId,
316 @Nullable ZonedDateTime startTime, @Nullable ZonedDateTime endTime,
317 @Nonnull QueryParameter queryParameter )
318 throws MetadataRepositoryException;
322 * Returns all the artifacts who's 'whenGathered' attribute value is inside the given time range (inclusive) as stream of objects.
324 * Implementations should return a stream of sorted objects. The objects should be sorted by the 'whenGathered' date in ascending order.
326 * @param session The repository session
327 * @param repositoryId The repository id
328 * @param startTime The start time, can be <code>null</code>
329 * @param endTime The end time, can be <code>null</code>
330 * @return A stream of artifact metadata objects.
331 * @throws MetadataRepositoryException
334 Stream<ArtifactMetadata> getArtifactByDateRangeStream( @Nonnull RepositorySession session, @Nonnull String repositoryId,
335 @Nullable ZonedDateTime startTime, @Nullable ZonedDateTime endTime )
336 throws MetadataRepositoryException;
339 * Returns all the artifacts who's 'whenGathered' attribute value is inside the given time range (inclusive) as stream of objects.
341 * If no sort attributes are given by the queryParameter, the result is sorted by the 'whenGathered' date.
343 * @param session The repository session
344 * @param repositoryId The repository id
345 * @param startTime The start time, can be <code>null</code>
346 * @param endTime The end time, can be <code>null</code>
347 * @param queryParameter Additional parameters for the query that affect ordering and number of returned results.
348 * @return A stream of artifact metadata objects.
349 * @throws MetadataRepositoryException
352 Stream<ArtifactMetadata> getArtifactByDateRangeStream( @Nonnull RepositorySession session, @Nonnull String repositoryId,
353 @Nullable ZonedDateTime startTime, @Nullable ZonedDateTime endTime,
354 @Nonnull QueryParameter queryParameter)
355 throws MetadataRepositoryException;
359 * Returns the artifacts that match the given checksum. All checksum types are searched.
361 * @param session The repository session
362 * @param repositoryId The repository id
363 * @param checksum The checksum as string of numbers
364 * @return The list of artifacts that match the given checksum.
365 * @throws MetadataRepositoryException
367 List<ArtifactMetadata> getArtifactsByChecksum(@Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull String checksum )
368 throws MetadataRepositoryException;
371 * Get artifacts with a project version metadata key that matches the passed value.
377 * @param repositoryId can be null, meaning search in all repositories
378 * @return a list of artifacts
379 * @throws MetadataRepositoryException
381 List<ArtifactMetadata> getArtifactsByProjectVersionMetadata( @Nonnull RepositorySession session, @Nonnull String key, @Nonnull String value,
382 @Nullable String repositoryId )
383 throws MetadataRepositoryException;
386 * Get artifacts with an artifact metadata key that matches the passed value.
392 * @param repositoryId can be null, meaning search in all repositories
393 * @return a list of artifacts
394 * @throws MetadataRepositoryException
396 List<ArtifactMetadata> getArtifactsByMetadata( RepositorySession session, String key, String value, String repositoryId )
397 throws MetadataRepositoryException;
400 * Get artifacts with a property key that matches the passed value.
401 * Possible keys are 'scm.url', 'org.name', 'url', 'mailingList.0.name', 'license.0.name',...
407 * @param repositoryId can be null, meaning search in all repositories
408 * @return a list of artifacts
409 * @throws MetadataRepositoryException
411 List<ArtifactMetadata> getArtifactsByProperty( RepositorySession session, String key, String value, String repositoryId )
412 throws MetadataRepositoryException;
414 void removeArtifact( RepositorySession session, String repositoryId, String namespace, String project, String version, String id )
415 throws MetadataRepositoryException;
418 * used for deleting timestamped version of SNAPSHOT artifacts
422 * @param artifactMetadata the artifactMetadata with the timestamped version (2.0-20120618.214135-2)
423 * @param baseVersion the base version of the snapshot (2.0-SNAPSHOT)
424 * @throws MetadataRepositoryException
427 void removeArtifact( RepositorySession session, ArtifactMetadata artifactMetadata, String baseVersion )
428 throws MetadataRepositoryException;
431 * FIXME need a unit test!!!
432 * Only remove {@link MetadataFacet} for the artifact
436 * @param repositoryId
440 * @param metadataFacet
441 * @throws MetadataRepositoryException
444 void removeArtifact( RepositorySession session, String repositoryId, String namespace, String project, String version,
445 MetadataFacet metadataFacet )
446 throws MetadataRepositoryException;
449 * Delete a repository's metadata. This includes all associated metadata facets.
452 * @param repositoryId the repository to delete
454 void removeRepository( RepositorySession session, String repositoryId )
455 throws MetadataRepositoryException;
460 * @param repositoryId
461 * @param namespace (groupId for maven )
462 * @throws MetadataRepositoryException
465 void removeNamespace( RepositorySession session, String repositoryId, String namespace )
466 throws MetadataRepositoryException;
468 List<ArtifactMetadata> getArtifacts( RepositorySession session, String repositoryId )
469 throws MetadataRepositoryException;
472 * Returns a stream of artifacts that are stored in the given repository. The number and order of elements in the stream
473 * is defined by the <code>queryParameter</code>.
474 * The efficiency of ordering of elements is dependent on the implementation.
475 * There may be some implementations that have to put a hard limit on the elements returned.
476 * If there are no <code>sortFields</code> defined in the query parameter, the order of elements in the stream is undefined and depends
477 * on the implementation.
480 * @param repositoryId
481 * @return A stream of artifact metadata objects for each artifact found in the repository.
484 Stream<ArtifactMetadata> getArtifactStream( @Nonnull RepositorySession session, @Nonnull String repositoryId, @Nonnull QueryParameter queryParameter )
485 throws MetadataResolutionException;
488 * Returns a stream of all the artifacts in the given repository using default query parameter.
489 * The order of the artifacts returned in the stream depends on the implementation.
490 * The number of elements in the stream is unlimited, but there may be some implementations that have to put a hard
491 * limit on the elements returned.
492 * For further information see {@link #getArtifactStream(RepositorySession, String, QueryParameter)}
494 * @param session The repository session
495 * @param repositoryId The repository id
496 * @return A (unlimited) stream of artifact metadata elements that are found in this repository
498 * @see #getArtifactStream(RepositorySession, String, QueryParameter)
500 Stream<ArtifactMetadata> getArtifactStream( @Nonnull RepositorySession session, @Nonnull String repositoryId)
501 throws MetadataResolutionException;
504 * Returns a stream of artifacts found for the given artifact coordinates and using the <code>queryParameter</code>
506 * @param session The repository session. May not be <code>null</code>.
507 * @param repoId The repository id. May not be <code>null</code>.
508 * @param namespace The namespace. May not be <code>null</code>.
509 * @param projectId The project id. May not be <code>null</code>.
510 * @param projectVersion The project version. May not be <code>null</code>.
511 * @return A stream of artifact metadata object. Order and number of elements returned, depends on the <code>queryParameter</code>.
513 * @throws MetadataResolutionException if there are no elements for the given artifact coordinates.
515 Stream<ArtifactMetadata> getArtifactStream( @Nonnull RepositorySession session, @Nonnull String repoId,
516 @Nonnull String namespace, @Nonnull String projectId,
517 @Nonnull String projectVersion, @Nonnull QueryParameter queryParameter )
518 throws MetadataResolutionException;
521 * Returns a stream of artifacts found for the given artifact coordinates. The order of elements returned, depends on the
524 * @param session The repository session. May not be <code>null</code>.
525 * @param repoId The repository id. May not be <code>null</code>.
526 * @param namespace The namespace. May not be <code>null</code>.
527 * @param projectId The project id. May not be <code>null</code>.
528 * @param projectVersion The project version. May not be <code>null</code>.
529 * @return A stream of artifact metadata object. Order and number of elements returned, depends on the <code>queryParameter</code>.
531 * @throws MetadataResolutionException if there are no elements for the given artifact coordinates.
533 Stream<ArtifactMetadata> getArtifactStream( @Nonnull RepositorySession session, @Nonnull String repoId,
534 @Nonnull String namespace, @Nonnull String projectId,
535 @Nonnull String projectVersion)
536 throws MetadataResolutionException;
538 * basically just checking it exists not complete data returned
546 * @throws MetadataResolutionException
548 ProjectMetadata getProject( RepositorySession session, String repoId, String namespace, String projectId )
549 throws MetadataResolutionException;
551 ProjectVersionMetadata getProjectVersion( RepositorySession session, String repoId, String namespace, String projectId, String projectVersion )
552 throws MetadataResolutionException;
554 Collection<String> getArtifactVersions( RepositorySession session, String repoId, String namespace, String projectId, String projectVersion )
555 throws MetadataResolutionException;
558 * Retrieve project references from the metadata repository. Note that this is not built into the content model for
559 * a project version as a reference may be present (due to reverse-lookup of dependencies) before the actual
560 * project is, and we want to avoid adding a stub model to the content repository.
564 * @param repoId the repository ID to look within
565 * @param namespace the namespace of the project to get references to
566 * @param projectId the identifier of the project to get references to
567 * @param projectVersion the version of the project to get references to
568 * @return a list of project references
570 Collection<ProjectVersionReference> getProjectReferences( RepositorySession session, String repoId, String namespace, String projectId,
571 String projectVersion )
572 throws MetadataResolutionException;
574 Collection<String> getRootNamespaces( RepositorySession session, String repoId )
575 throws MetadataResolutionException;
582 * @return {@link Collection} of child namespaces of the namespace argument
583 * @throws MetadataResolutionException
585 Collection<String> getNamespaces( RepositorySession session, String repoId, String namespace )
586 throws MetadataResolutionException;
594 * @throws MetadataResolutionException
596 Collection<String> getProjects( RepositorySession session, String repoId, String namespace )
597 throws MetadataResolutionException;
606 * @throws MetadataResolutionException
608 Collection<String> getProjectVersions( RepositorySession session, String repoId, String namespace, String projectId )
609 throws MetadataResolutionException;
617 * @param projectVersion
618 * @throws MetadataRepositoryException
621 void removeProjectVersion( RepositorySession session, String repoId, String namespace, String projectId, String projectVersion )
622 throws MetadataRepositoryException;
630 * @param projectVersion
632 * @throws MetadataResolutionException
634 Collection<ArtifactMetadata> getArtifacts( RepositorySession session, String repoId, String namespace, String projectId,
635 String projectVersion )
636 throws MetadataResolutionException;
643 * @param repositoryId
646 * @throws MetadataRepositoryException
649 void removeProject( RepositorySession session, String repositoryId, String namespace, String projectId )
650 throws MetadataRepositoryException;
654 throws MetadataRepositoryException;
657 boolean canObtainAccess( Class<?> aClass );
659 <T> T obtainAccess( RepositorySession session, Class<T> aClass )
660 throws MetadataRepositoryException;
663 * Full text artifacts search.
667 * @param repositoryId can be null to search in all repositories
669 * @param exact running an exact search, the value must exactly match the text.
670 * @return a list of artifacts
671 * @throws MetadataRepositoryException
673 List<ArtifactMetadata> searchArtifacts( RepositorySession session, String repositoryId, String text, boolean exact )
674 throws MetadataRepositoryException;
677 * Full text artifacts search inside the specified key.
681 * @param repositoryId can be null to search in all repositories
682 * @param key search only inside this key
684 * @param exact running an exact search, the value must exactly match the text.
685 * @return a list of artifacts
686 * @throws MetadataRepositoryException
688 List<ArtifactMetadata> searchArtifacts( RepositorySession session, String repositoryId, String key, String text, boolean exact )
689 throws MetadataRepositoryException;