Java tutorial
/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/commons-ip */ package org.roda_project.commons_ip.model.impl.eark; import java.io.IOException; import java.nio.channels.ClosedByInterruptException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.roda_project.commons_ip.mets_v1_11.beans.StructMapType; import org.roda_project.commons_ip.model.IPConstants; import org.roda_project.commons_ip.model.IPContentType; import org.roda_project.commons_ip.model.MetsWrapper; import org.roda_project.commons_ip.model.ParseException; import org.roda_project.commons_ip.model.SIP; import org.roda_project.commons_ip.model.impl.ModelUtils; import org.roda_project.commons_ip.utils.IPException; import org.roda_project.commons_ip.utils.METSUtils; import org.roda_project.commons_ip.utils.ZIPUtils; import org.roda_project.commons_ip.utils.ZipEntryInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EARKSIP extends SIP { private static final Logger LOGGER = LoggerFactory.getLogger(EARKSIP.class); private static final String SIP_TEMP_DIR = "EARKSIP"; private static final String SIP_FILE_EXTENSION = ".zip"; public EARKSIP() { super(); } /** * @param sipId * will be used as OBJID in METS (/mets[@OBJID]) */ public EARKSIP(String sipId) { super(sipId); } /** * @param sipId * will be used as OBJID in METS (/mets[@OBJID]) */ public EARKSIP(String sipId, IPContentType contentType) { super(sipId, contentType); } /** * * build and all build related methods * _________________________________________________________________________ */ @Override public Path build(Path destinationDirectory) throws IPException, InterruptedException { return build(destinationDirectory, null); } /** * Builds a SIP. * * @param destinationDirectory * the {@link Path} where the SIP should be build. * @param onlyManifest * build only the manifest file? (<strong>this parameter is * ignored</strong>). * @return the {@link Path}. * @throws IPException * if some error occurs. * @throws InterruptedException * if some error occurs. */ @Override public Path build(final Path destinationDirectory, final boolean onlyManifest) throws IPException, InterruptedException { return build(destinationDirectory, null); } @Override public Path build(Path destinationDirectory, String fileNameWithoutExtension) throws IPException, InterruptedException { return build(destinationDirectory, fileNameWithoutExtension, false); } /** * * build and all build related methods * _________________________________________________________________________ */ /** * Builds a SIP. * * @param destinationDirectory * the {@link Path} where the SIP should be build. * @param fileNameWithoutExtension * the name of the output file without extension. * @param onlyManifest * build only the manifest file? (<strong>this parameter is * ignored</strong>). * @return the {@link Path}. * @throws IPException * if some error occurs. * @throws InterruptedException * if some error occurs. */ @Override public Path build(final Path destinationDirectory, final String fileNameWithoutExtension, final boolean onlyManifest) throws IPException, InterruptedException { IPConstants.METS_ENCODE_AND_DECODE_HREF = true; Path buildDir = ModelUtils.createBuildDir(SIP_TEMP_DIR); Path zipPath = getZipPath(destinationDirectory, fileNameWithoutExtension); try { Map<String, ZipEntryInfo> zipEntries = getZipEntries(); // 20160407 hsilva: as METS does not have an attribute 'otherType', the // other type must be put in the 'type' attribute allowing this way other // values besides the ones in the Enum String contentType = this.getContentType().asString(); MetsWrapper mainMETSWrapper = EARKMETSUtils.generateMETS(StringUtils.join(this.getIds(), " "), this.getDescription(), this.getType() + ":" + contentType, this.getProfile(), true, Optional.ofNullable(this.getAncestors()), null, this.getHeader()); EARKUtils.addDescriptiveMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getDescriptiveMetadata(), null); EARKUtils.addPreservationMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getPreservationMetadata(), null); EARKUtils.addOtherMetadataToZipAndMETS(zipEntries, mainMETSWrapper, getOtherMetadata(), null); EARKUtils.addRepresentationsToZipAndMETS(this, getRepresentations(), zipEntries, mainMETSWrapper, buildDir); EARKUtils.addDefaultSchemas(LOGGER, getSchemas(), buildDir); EARKUtils.addSchemasToZipAndMETS(zipEntries, mainMETSWrapper, getSchemas(), null); EARKUtils.addDocumentationToZipAndMETS(zipEntries, mainMETSWrapper, getDocumentation(), null); METSUtils.addMainMETSToZip(zipEntries, mainMETSWrapper, buildDir); createZipFile(zipEntries, zipPath); return zipPath; } catch (InterruptedException e) { ModelUtils.cleanUpUponInterrupt(LOGGER, zipPath); throw e; } finally { ModelUtils.deleteBuildDir(buildDir); } } private Path getZipPath(Path destinationDirectory, String fileNameWithoutExtension) throws IPException { Path zipPath; if (fileNameWithoutExtension != null) { zipPath = destinationDirectory.resolve(fileNameWithoutExtension + SIP_FILE_EXTENSION); } else { zipPath = destinationDirectory.resolve(getId() + SIP_FILE_EXTENSION); } try { if (Files.exists(zipPath)) { Files.delete(zipPath); } } catch (IOException e) { throw new IPException("Error deleting already existing zip", e); } return zipPath; } private void createZipFile(Map<String, ZipEntryInfo> zipEntries, Path zipPath) throws IPException, InterruptedException { try { notifySipBuildPackagingStarted(zipEntries.size()); ZIPUtils.zip(zipEntries, Files.newOutputStream(zipPath), this, false, true); } catch (ClosedByInterruptException e) { throw new InterruptedException(); } catch (IOException e) { throw new IPException("Error generating E-ARK SIP ZIP file. Reason: " + e.getMessage(), e); } finally { notifySipBuildPackagingEnded(); } } /** * * parse and all parse related methods; during parse, validation is also * conducted and stored inside the SIP * _________________________________________________________________________ */ public static SIP parse(Path source, Path destinationDirectory) throws ParseException { return parseEARKSIP(source, destinationDirectory); } public static SIP parse(Path source) throws ParseException { try { return parse(source, Files.createTempDirectory("unzipped")); } catch (IOException e) { throw new ParseException("Error creating temporary directory for E-ARK SIP parse", e); } } private static SIP parseEARKSIP(final Path source, final Path destinationDirectory) throws ParseException { try { IPConstants.METS_ENCODE_AND_DECODE_HREF = true; SIP sip = new EARKSIP(); Path sipPath = ZIPUtils.extractIPIfInZipFormat(source, destinationDirectory); sip.setBasePath(sipPath); MetsWrapper metsWrapper = EARKUtils.processMainMets(sip, sipPath); if (sip.isValid()) { StructMapType structMap = EARKUtils.getEARKStructMap(metsWrapper, sip, true); if (structMap != null) { EARKUtils.preProcessStructMap(metsWrapper, structMap); EARKUtils.processDescriptiveMetadata(metsWrapper, sip, LOGGER, null, sip.getBasePath()); EARKUtils.processOtherMetadata(metsWrapper, sip, LOGGER, null, sip.getBasePath()); EARKUtils.processPreservationMetadata(metsWrapper, sip, LOGGER, null, sip.getBasePath()); EARKUtils.processRepresentations(metsWrapper, sip, LOGGER); EARKUtils.processSchemasMetadata(metsWrapper, sip, sip.getBasePath()); EARKUtils.processDocumentationMetadata(metsWrapper, sip, sip.getBasePath()); EARKUtils.processAncestors(metsWrapper, sip); } } return sip; } catch (final IPException e) { throw new ParseException("Error parsing E-ARK SIP", e); } } @Override public Set<String> getExtraChecksumAlgorithms() { return Collections.emptySet(); } }