001/* 002 * #%L 003 * Netarchivesuite - archive 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.archive.checksum.distribute; 024 025import java.io.File; 026 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030import dk.netarkivet.archive.distribute.ArchiveMessage; 031import dk.netarkivet.archive.distribute.ArchiveMessageVisitor; 032import dk.netarkivet.common.distribute.ChannelID; 033import dk.netarkivet.common.distribute.RemoteFile; 034import dk.netarkivet.common.exceptions.ArgumentNotValid; 035import dk.netarkivet.common.exceptions.IOFailure; 036 037/** 038 * The message to correct a bad entry in an archive. <li>In a bitarchive it should replace a corrupted file.</li> <li>In 039 * a checksum archive it should replace checksum entry of the file.</li> <br> 040 * The message contains the checksum of the 'bad' entry in the archive, which is only corrected if it actually has this 041 * 'bad checksum'. 042 */ 043@SuppressWarnings({"serial"}) 044public class CorrectMessage extends ArchiveMessage { 045 046 private static final Logger log = LoggerFactory.getLogger(CorrectMessage.class); 047 048 /** The file to replace the current bad entry. */ 049 private RemoteFile theRemoteFile; 050 /** The name of the arc-file. */ 051 private String arcFilename; 052 /** The 'bad' checksum. */ 053 private String theIncorrectChecksum; 054 /** The replica, where this message should be sent. */ 055 private String replicaId; 056 /** The credentials to allow the correction of the archive entry. */ 057 private String credentials; 058 /** The 'removed' file, which has to be returned. */ 059 private RemoteFile removedFile; 060 061 /** 062 * Constructor. Initializes the variables. 063 * 064 * @param to Where the message should be sent. 065 * @param replyTo Who is sending this message. 066 * @param badChecksum The checksum of the 'bad' entry. 067 * @param rf The remote file to replace the 'bad' entry. 068 * @param repId The identification of the replica, where this message should be sent. 069 * @param cred The credentials to allow the correction of an entry. 070 * @throws ArgumentNotValid If any of the arguments are null, or any of the strings are empty. 071 */ 072 public CorrectMessage(ChannelID to, ChannelID replyTo, String badChecksum, RemoteFile rf, String repId, String cred) 073 throws ArgumentNotValid { 074 super(to, replyTo); 075 // Validate arguments ('super' validates the channels). 076 ArgumentNotValid.checkNotNull(rf, "RemoteFile file"); 077 ArgumentNotValid.checkNotNullOrEmpty(badChecksum, "String badChecksum"); 078 ArgumentNotValid.checkNotNullOrEmpty(repId, "String repId"); 079 ArgumentNotValid.checkNotNullOrEmpty(cred, "String cred"); 080 this.theIncorrectChecksum = badChecksum; 081 this.theRemoteFile = rf; 082 this.arcFilename = rf.getName(); 083 this.replicaId = repId; 084 this.credentials = cred; 085 } 086 087 /** 088 * Retrieve name of the uploaded file. 089 * 090 * @return current value of arcfileName 091 */ 092 public String getArcfileName() { 093 return arcFilename; 094 } 095 096 /** 097 * Retrieves the content of the remoteFile and writes it into the local file. Note: This is transferred through a 098 * remote file handle, and then the handle is invalidated. This method may only be called once. 099 * 100 * @param toFile where to write the content 101 * @throws IOFailure on error reading the remote file or writing the local file 102 * @throws ArgumentNotValid If <b>toFile</b> is null. 103 */ 104 public void getData(File toFile) throws IOFailure, ArgumentNotValid { 105 ArgumentNotValid.checkNotNull(toFile, "toFile"); 106 107 // ensure that the local file exists. 108 if (theRemoteFile == null) { 109 throw new IOFailure("No remoteFile in this message."); 110 } 111 // retrieve the data. 112 theRemoteFile.copyTo(toFile); 113 try { 114 // cleanup afterwards. 115 theRemoteFile.cleanup(); 116 } catch (IOFailure e) { 117 // Just log errors on deleting. They are fairly harmless. 118 // Can't make Logger a field, as this class is Serializable 119 log.warn("Could not cleanup remote file {}", theRemoteFile.getName()); 120 } 121 theRemoteFile = null; 122 } 123 124 /** 125 * Method for retrieving the correct file. 126 * 127 * @return The RemoteFile for the correct file. 128 */ 129 public RemoteFile getCorrectFile() { 130 return theRemoteFile; 131 } 132 133 /** 134 * Method for retrieving the 'bad' checksum which should correspond to the checksum of the current entry on this 135 * file in the archive. 136 * 137 * @return The checksum for the archive entry. 138 */ 139 public String getIncorrectChecksum() { 140 return theIncorrectChecksum; 141 } 142 143 /** 144 * Method for retrieving the replica, where this message should be sent. 145 * 146 * @return The id of the replica where this message should be sent. 147 */ 148 public String getReplicaId() { 149 return replicaId; 150 } 151 152 /** 153 * The credentials to allow correction of an entry in the archive. 154 * 155 * @return The credentials. 156 */ 157 public String getCredentials() { 158 return credentials; 159 } 160 161 /** 162 * Returns the removed file. 163 * 164 * @return The removed file. 165 * @throws IOFailure If the removed file is null. 166 */ 167 public RemoteFile getRemovedFile() throws IOFailure { 168 if (removedFile == null) { 169 log.warn("The removed file is null. Perhaps the message has not been sent."); 170 } 171 return removedFile; 172 } 173 174 /** 175 * Sets the removed file. This is the file which are returned to the sender of the message. 176 * 177 * @param rf The removed file which is part of the reply of this message. 178 * @throws ArgumentNotValid If the remote file is null. 179 */ 180 public void setRemovedFile(RemoteFile rf) throws ArgumentNotValid { 181 ArgumentNotValid.checkNotNull(rf, "RemoteFile rf"); 182 removedFile = rf; 183 } 184 185 /** 186 * Accept this message. 187 * 188 * @param v The message visitor accepting this message. 189 */ 190 public void accept(ArchiveMessageVisitor v) { 191 v.visit(this); 192 } 193 194 /** 195 * Generate String representation of this object. 196 * 197 * @return String representation of this object 198 */ 199 public String toString() { 200 return super.toString() + ", Arcfile: " + arcFilename + ", Removed: " + (removedFile != null); 201 } 202 203}