/** * IPManagementTasks.java * Author: Francesco Rosso (rosso@eurix.it) * * This file is part of PrestoPRIME Preservation Platform (P4). * * Copyright (C) 2012 EURIX Srl, Torino, Italy * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.prestoprime.plugin.p4; import it.eurix.archtools.data.DataException; import it.eurix.archtools.data.model.AIP; import it.eurix.archtools.data.model.DIP.DCField; import it.eurix.archtools.data.model.IPException; import it.eurix.archtools.data.model.SIP; import it.eurix.archtools.tool.ToolException; import it.eurix.archtools.tool.ToolOutput; import it.eurix.archtools.tool.impl.MessageDigestExtractor; import it.eurix.archtools.workflow.exceptions.TaskExecutionFailedException; import it.eurix.archtools.workflow.plugin.WfPlugin; import it.eurix.archtools.workflow.plugin.WfPlugin.WfService; import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import eu.prestoprime.datamanagement.P4DataManager; @WfPlugin(name = "P4Plugin") public class IPManagementTasks { private static final Logger logger = LoggerFactory.getLogger(IPManagementTasks.class); @WfService(name = "validate_sip", version = "2.2.0") public void validateSIP(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamsFile) throws TaskExecutionFailedException { // get dynamic variables File sipFile = dParamsFile.get("sipFile"); // parse the SIP String sipID; try { sipID = P4DataManager.getInstance().createNewSIP(sipFile); } catch (DataException e) { e.printStackTrace(); logger.error("Unable to create new SIP..."); throw new TaskExecutionFailedException("Unable to create new SIP..."); } // send sipID to following tasks dParamsString.put("sipID", sipID); // get the SIP SIP sip = null; try { sip = P4DataManager.getInstance().getSIPByID(sipID); // check DC identifier in AIP_COLLECTION for (String identifier : sip.getDCField(DCField.identifier)) { String tmpID = P4DataManager.getInstance().getAIPByDCID(identifier); if (tmpID != null) throw new TaskExecutionFailedException("Found another AIP with same DC identifier..."); } // check DC title if (sip.getDCField(DCField.title).size() == 0) throw new TaskExecutionFailedException("Invalid SIP, missing title..."); for (String title : sip.getDCField(DCField.title)) { if (title.length() > 0) continue; else throw new TaskExecutionFailedException("Invalid SIP, empty title..."); } // set DC date if (sip.getDCField(DCField.date).size() == 0) { List<String> dateList = new ArrayList<>(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // ISO 8601 String date = df.format(new Date()); dateList.add(date); sip.setDCField(DCField.date, dateList); } } catch (DataException e) { e.printStackTrace(); logger.error("Unable to retrieve the just created SIP..."); throw new TaskExecutionFailedException("Unable to retrieve the just created SIP..."); } catch (IPException e) { e.printStackTrace(); logger.error("Unable to retrieve DC identifier..."); throw new TaskExecutionFailedException("Unable to retrieve DC identifier..."); } finally { P4DataManager.getInstance().releaseIP(sip); } } @WfService(name = "verify_sip", version = "2.2.0") public void verifySIP(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamsFile) throws TaskExecutionFailedException { // get SIP id String sipID = dParamsString.get("sipID"); // get SIP SIP sip = null; try { sip = P4DataManager.getInstance().getSIPByID(sipID); if (sip.getDCField(DCField.description).size() == 0) { List<String> description = new ArrayList<>(); description.add(""); sip.setDCField(DCField.description, description); } boolean rightsOnly = Boolean.parseBoolean(sParams.get("rights_only")); boolean hasAVMaterial = sip.hasAVMaterial(); boolean hasRights = sip.hasRights(); // check rights if (rightsOnly) { // rights only if (hasAVMaterial || !hasRights) { throw new TaskExecutionFailedException("SIP rights_only with AV material or without Rights..."); } } else { // not rights only if (!hasAVMaterial) { throw new TaskExecutionFailedException("SIP not rights_only without AV material..."); } else { List<String> formatList = sip.getAVFormats(); String mqFormat = null; String mqFilePath = null; int numOfAVFiles = 0; // check SIP with only one valid MQ file for (String format : formatList) { if (sip.getAVMaterial(format, "FILE").size() != 1) throw new TaskExecutionFailedException("SIP with too few or too many AV files..."); else { numOfAVFiles = numOfAVFiles + sip.getAVMaterial(format, "FILE").size(); mqFormat = format; mqFilePath = sip.getAVMaterial(format, "FILE").get(0); } } if (numOfAVFiles != 1 && mqFormat != null && mqFilePath != null) throw new TaskExecutionFailedException("SIP with no suitable AV format or different master quality formats..."); logger.debug("Number of AV files: " + numOfAVFiles + " MQ format: " + mqFilePath + " MQ path: " + mqFilePath); // compare computed checksum with the value from provider // (if any) String providerChecksum = sip.getChecksum(mqFormat, "MD5"); logger.debug("Checksum from provider: " + providerChecksum); if (providerChecksum != null) { MessageDigestExtractor mde = new MessageDigestExtractor(); ToolOutput<MessageDigestExtractor.AttributeType> output = mde.extract(mqFilePath); String computedChecksum = output.getAttribute(MessageDigestExtractor.AttributeType.MD5); if (!providerChecksum.equals(computedChecksum)) throw new TaskExecutionFailedException("Invalid checksum from SIP provider or wrong file..."); } } } } catch (DataException e) { e.printStackTrace(); } catch (IPException e) { e.printStackTrace(); } catch (ToolException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { P4DataManager.getInstance().releaseIP(sip); } } @WfService(name = "consolidate_aip", version = "2.1.0") public void consolidateAIP(Map<String, String> sParams, Map<String, String> dParamsString, Map<String, File> dParamsFile) throws TaskExecutionFailedException { // get sipID String sipID = dParamsString.get("sipID"); // consolidate try { SIP sip = P4DataManager.getInstance().getSIPByID(sipID); try { sip.purgeFiles(); } catch (IPException e) { e.printStackTrace(); P4DataManager.getInstance().releaseIP(sip); throw new TaskExecutionFailedException("Unable to purge files..."); } dParamsString.put("result", sip.toString()); P4DataManager.getInstance().consolidateSIP(sip); sip = null; } catch (DataException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to consolidate the SIP..."); } String aipID = sipID; AIP aip = null; try { aip = P4DataManager.getInstance().getAIPByID(aipID); aip.addPreservationEvent("INGESTION", "status=success"); } catch (DataException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to retrieve the just created AIP..."); } catch (IPException e) { e.printStackTrace(); throw new TaskExecutionFailedException("Unable to add a new preservation event..."); } finally { P4DataManager.getInstance().releaseIP(aip); } } }