Class CollectionArchiveService
<collectionArchives> in config_viewer.xml.
Responsibilities:
- build the collection-selector query with the anonymous access / static / blacklist suffixes (record-level pre-filter), with all indexed values Solr-escaped to prevent query injection;
- enforce page-level access when assembling the payload: per-file for images/ALTO/plaintext (only anonymously-accessible files are packed), and a whole-record "fully open" gate for the METS/LIDO source and TEI;
- decide whether a collection's archive needs (re)generation by comparing the current record count and maximum
SolrConstants.DATEINDEXEDagainst the values encoded in the existing archive's file name; - assemble the enabled content types into a bag's
data/directory, write it viaBagItWriter, and atomically move it into the storage folder; - locate and describe existing archives for the download endpoint / collection page, and prune orphaned archives.
Archive files are named <slug>__n<recordCount>__u<maxIndexedMillis>.zip; this file name is the sole persisted state (no sidecar
manifest, no database table).
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordImmutable description of an existing archive on disk, as recovered from its file name.static final recordOutcome of agenerateIfChanged(String, String, CollectionArchiveConfig)call. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic StringbuildCollectionQuery(String field, String collectionName) Builds the full Solr query selecting the freely-accessible top-level records of a collection (and its sub-collections).voiddeleteExistingArchives(String field, String collectionName) Deletes all archive files for a collection.findArchive(String field, String collectionName) Finds the current archive file for a collection, if one exists.generateIfChanged(String field, String collectionName, CollectionArchiveConfig archiveConfig) Generates the archive for a single collection if (and only if) it does not yet exist or its content has changed since the last generation, as determined by comparing the current record count and maximum DATEINDEXED against the state encoded in the existing archive's file name.getFieldFolder(String field) voidpruneOrphans(String field, Set<String> liveSlugs) Removes archive files under a field's folder whose collection slug is not present inliveSlugs(i.e. the collection no longer exists in the index or is no longer configured for archiving).static StringBuilds a filesystem-safe slug from a collection (or field) name.
-
Constructor Details
-
CollectionArchiveService
public CollectionArchiveService()Creates a service using the globalDataManagerconfiguration. -
CollectionArchiveService
- Parameters:
config- the configuration to read archive settings and data-folder names from
-
-
Method Details
-
getStorageBaseFolder
- Returns:
- the base storage folder for all collection archives (
<viewerHome>/<collectionArchivesFolder>)
-
getFieldFolder
- Parameters:
field- the collection Solr field (validated by the caller against the configured allow-list)- Returns:
- the storage folder holding archives for the given field
-
slugify
Builds a filesystem-safe slug from a collection (or field) name. All characters outside[A-Za-z0-9.-]are replaced with an underscore, so the slug can never contain a path separator or traversal sequence.- Parameters:
name- the raw name- Returns:
- a slug safe for use as a single path segment
-
findArchive
public Optional<CollectionArchiveService.ArchiveInfo> findArchive(String field, String collectionName) throws IOException Finds the current archive file for a collection, if one exists.- Parameters:
field- the collection Solr fieldcollectionName- the collection name- Returns:
- the archive description, or empty if none exists
- Throws:
IOException- on directory read error
-
buildCollectionQuery
Builds the full Solr query selecting the freely-accessible top-level records of a collection (and its sub-collections). The collection name is escaped both as a phrase and as a wildcard prefix to prevent query injection.Access, static-query and collection-blacklist filtering are delegated to
SearchHelper.getAllSuffixes(HttpServletRequest, boolean, boolean)with anullrequest, which evaluates the access filter for an anonymous principal (failing closed toOPENACCESS-only), appends the configured<staticQuerySuffix>, and excludes blacklisted DC collections. This is a coarse record-level pre-filter; page-level access is enforced per file when the payload is assembled (seepopulateAccessFilteredFolders(io.goobi.viewer.model.export.bagit.ArchiveContentType, java.nio.file.Path, java.util.List<org.apache.solr.common.SolrDocument>, java.lang.String, java.lang.String, java.lang.String, io.goobi.viewer.model.export.bagit.CollectionArchiveService.PopulationStats)andhasRestrictedFulltextPage(java.lang.String)).- Parameters:
field- the collection Solr fieldcollectionName- the collection name- Returns:
- the combined Solr query string
-
generateIfChanged
public CollectionArchiveService.GenerationResult generateIfChanged(String field, String collectionName, CollectionArchiveConfig archiveConfig) throws PresentationException, IndexUnreachableException, DAOException, IOException, ViewerConfigurationException Generates the archive for a single collection if (and only if) it does not yet exist or its content has changed since the last generation, as determined by comparing the current record count and maximum DATEINDEXED against the state encoded in the existing archive's file name.- Parameters:
field- the collection Solr fieldcollectionName- the collection namearchiveConfig- the resolved set of content types to include- Returns:
- a
CollectionArchiveService.GenerationResultindicating whether an archive was (re)generated and a human-readable detail (content summary when generated, or the reason when skipped) - Throws:
PresentationException- on Solr query errorsIndexUnreachableException- if the Solr index is unreachableDAOException- if license types cannot be loadedIOException- on filesystem errorsViewerConfigurationException- on export configuration errors
-
deleteExistingArchives
Deletes all archive files for a collection.- Parameters:
field- the collection Solr fieldcollectionName- the collection name- Throws:
IOException- on filesystem error
-
pruneOrphans
Removes archive files under a field's folder whose collection slug is not present inliveSlugs(i.e. the collection no longer exists in the index or is no longer configured for archiving).- Parameters:
field- the collection Solr fieldliveSlugs- the set of slugs for collections that should retain their archives- Throws:
IOException- on filesystem error
-