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 org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028import dk.netarkivet.archive.bitarchive.distribute.BatchMessage; 029import dk.netarkivet.archive.bitarchive.distribute.GetFileMessage; 030import dk.netarkivet.archive.bitarchive.distribute.GetMessage; 031import dk.netarkivet.archive.bitarchive.distribute.RemoveAndGetFileMessage; 032import dk.netarkivet.archive.bitarchive.distribute.UploadMessage; 033import dk.netarkivet.archive.distribute.ReplicaClient; 034import dk.netarkivet.common.distribute.ChannelID; 035import dk.netarkivet.common.distribute.Channels; 036import dk.netarkivet.common.distribute.JMSConnection; 037import dk.netarkivet.common.distribute.JMSConnectionFactory; 038import dk.netarkivet.common.distribute.RemoteFile; 039import dk.netarkivet.common.distribute.arcrepository.ReplicaType; 040import dk.netarkivet.common.exceptions.ArgumentNotValid; 041import dk.netarkivet.common.exceptions.IOFailure; 042import dk.netarkivet.common.exceptions.IllegalState; 043import dk.netarkivet.common.utils.batch.FileBatchJob; 044 045/** 046 * Proxy for remote checksum archive. Establishes the jms connection to the remote checksum archive. 047 * <p> 048 * Can be used in combination with any type of ChecksumServerAPI. 049 */ 050public class ChecksumClient implements ReplicaClient { 051 052 /** The log. */ 053 private static final Logger log = LoggerFactory.getLogger(ChecksumClient.class); 054 055 /** Connection to JMS provider. */ 056 private JMSConnection jmsCon; 057 058 /** Connection information. The connection to contact all checksum archives. */ 059 private ChannelID theChecksumChannel; 060 /** The name of the replica whose client this is. */ 061 private String replicaId; 062 063 /** 064 * The constructor. Cannot be used directly, use getInstance instead. 065 * 066 * @param theCRin The channel for contacting the checksum archive. 067 * @throws IOFailure If there is a problem with the connection. 068 */ 069 private ChecksumClient(ChannelID theCRin) throws IOFailure { 070 this.theChecksumChannel = theCRin; 071 replicaId = Channels.retrieveReplicaFromIdentifierChannel(theChecksumChannel.getName()).getId(); 072 jmsCon = JMSConnectionFactory.getInstance(); 073 } 074 075 /** 076 * The method for invoking an instance of this class. 077 * 078 * @param theCRin The channel for contacting the checksum archive. 079 * @return A new instance. 080 * @throws IOFailure If there is a problem with the connection. 081 * @throws ArgumentNotValid If the checksum replica channel is null. 082 */ 083 public static ChecksumClient getInstance(ChannelID theCRin) throws IOFailure, ArgumentNotValid { 084 // validate arguments 085 ArgumentNotValid.checkNotNull(theCRin, "ChannelID theCRin"); 086 087 // Create a new instance (no static instance, since it would prevent 088 // multi checksum replica clients). 089 return new ChecksumClient(theCRin); 090 } 091 092 /** 093 * Method for sending correct messages to the replica. This CorrectMessage is used to correct a bad entry in the 094 * archive. 095 * 096 * @param msg The CorrectMessage to send to the replica. 097 * @throws ArgumentNotValid If the CorrectMessage is null. 098 */ 099 public void sendCorrectMessage(CorrectMessage msg) throws ArgumentNotValid { 100 ArgumentNotValid.checkNotNull(msg, "CorrectMessage msg"); 101 102 // send the message to the archive. 103 jmsCon.resend(msg, theChecksumChannel); 104 105 // log the message. 106 log.debug("Resending CorrectMessage: {}'.", msg.toString()); 107 } 108 109 /** 110 * Method for sending a GetAllFilenamesMessage to a checksum archive. 111 * 112 * @param msg The GetAllFilenamesMessage, which will be send through the jms connection to the checksum archive. 113 * @throws ArgumentNotValid If the GetAllFilenamesMessage is null. 114 */ 115 public void sendGetAllFilenamesMessage(GetAllFilenamesMessage msg) throws ArgumentNotValid { 116 ArgumentNotValid.checkNotNull(msg, "GetAllFilenamesMessage msg"); 117 // send the message to the archive. 118 jmsCon.resend(msg, theChecksumChannel); 119 120 // log message. 121 log.debug("Resending GetAllFilenamesMessage: '{}'.", msg.toString()); 122 } 123 124 /** 125 * Method for sending the GetAllChecksumMessage to the ChecksumReplica. 126 * 127 * @param msg The GetAllChecksumMessage, which will be sent through the jms connection to the checksum archive. 128 * @throws ArgumentNotValid If the GetAllChecksumsMessage is null. 129 */ 130 public void sendGetAllChecksumsMessage(GetAllChecksumsMessage msg) throws ArgumentNotValid { 131 ArgumentNotValid.checkNotNull(msg, "GetAllChecksumsMessage msg"); 132 // send the message to the archive. 133 jmsCon.resend(msg, theChecksumChannel); 134 135 // log message. 136 log.debug("Sending GetAllChecksumMessage: '{}'.", msg.toString()); 137 } 138 139 /** 140 * Method for retrieving the checksum of a specific arcfile within the archive. 141 * 142 * @param msg The GetChecksumMessage which will be sent to the checksum archive though the jms connection. 143 */ 144 public void sendGetChecksumMessage(GetChecksumMessage msg) { 145 // Validate arguments 146 ArgumentNotValid.checkNotNull(msg, "GetChecksumMessage msg"); 147 148 jmsCon.resend(msg, theChecksumChannel); 149 150 // log what we are doing. 151 log.debug("Sending GetChecksumMessage: '{}'.", msg.toString()); 152 } 153 154 /** 155 * Method for retrieving the checksum of a specific arcfile within the archive. 156 * 157 * @param replyChannel The channel where the reply should be sent. 158 * @param filename The GetChecksumMessage which has been sent to the checksum archive though the jms connection. 159 * @return The GetChecksumMessage which is sent. 160 * @throws ArgumentNotValid If the reply channel is null or if the filename is either null or the empty string. 161 */ 162 public GetChecksumMessage sendGetChecksumMessage(ChannelID replyChannel, String filename) throws ArgumentNotValid { 163 // Validate arguments 164 ArgumentNotValid.checkNotNull(replyChannel, "ChannelID replyChannel"); 165 ArgumentNotValid.checkNotNullOrEmpty(filename, "String filename"); 166 167 // make GetChecksumMessage for the specific file. 168 GetChecksumMessage msg = new GetChecksumMessage(theChecksumChannel, replyChannel, filename, replicaId); 169 jmsCon.send(msg); 170 171 // log what we are doing. 172 log.debug("Sending GetChecksumMessage: '{}'.", msg.toString()); 173 174 return msg; 175 } 176 177 /** 178 * Method for retrieving the type of replica. In this case the replica is a checksum replica. 179 * 180 * @return The type of this replica, in this case Checksum replica. 181 */ 182 public ReplicaType getType() { 183 return ReplicaType.CHECKSUM; 184 } 185 186 /** 187 * Method for uploading a file to the archive. This is only uploaded to one of the archives, not all of them. Thus 188 * using the 'any' channel. 189 * 190 * @param rf The file to upload to the archive. 191 * @param precomputedChecksum A precomputed checksum 192 * @throws ArgumentNotValid If the remote file is null. 193 */ 194 public void sendUploadMessage(RemoteFile rf, String precomputedChecksum) throws ArgumentNotValid { 195 // validate arguments. 196 ArgumentNotValid.checkNotNull(rf, "RemoteFile rf"); 197 198 // create and send message. 199 UploadMessage up = new UploadMessage(theChecksumChannel, Channels.getTheRepos(), rf); 200 up.setPrecomputedChecksum(precomputedChecksum); 201 jmsCon.send(up); 202 203 // log message 204 log.debug("Sending upload message '{}'.", up.toString()); 205 } 206 207 /** 208 * Method for sending batch job messages to the replica. This is not allowed since this archive at the end of this 209 * client is a checksum archive, which cannot handle batch jobs. 210 * 211 * @param replyChannel The channel where the reply should be sent. 212 * @param job The batchjob to execute. 213 * @return Nothing. It always throws an exception, since it is not allowed to run batchjobs on a checksum archive. 214 * @throws IllegalState Always. Since it is not legal to send a batchjob to a checksum replica. 215 * @throws ArgumentNotValid If the channel or the batchjob is null. 216 */ 217 public BatchMessage sendBatchJob(ChannelID replyChannel, FileBatchJob job) throws IllegalState, ArgumentNotValid { 218 ArgumentNotValid.checkNotNull(replyChannel, "ChannelID replyChannel"); 219 ArgumentNotValid.checkNotNull(job, "FileBatchJob job"); 220 221 String errMsg = "Trying to execute the batchjob '" + job.getClass().getName() + "'" 222 + " on a checksum replica with reply " + "channel '" + replyChannel + "'. This is not allowed!"; 223 log.error(errMsg); 224 throw new IllegalState(errMsg); 225 } 226 227 /** 228 * Method for sending batch job messages to the replica. This is not allowed since this archive at the end of this 229 * client is a checksum archive, which cannot handle batch jobs. 230 * 231 * @param msg The batch message. 232 * @return Nothing. It always throws an exception, since it is not allowed to run batchjobs on a checksum archive. 233 * @throws IllegalState Always. Since it is not legal to send a batchjob to a checksum replica. 234 * @throws ArgumentNotValid If the message is null. 235 */ 236 public BatchMessage sendBatchJob(BatchMessage msg) throws IllegalState, ArgumentNotValid { 237 ArgumentNotValid.checkNotNull(msg, "BatchMessage msg"); 238 239 String errMsg = "Trying to execute the batchjob '" + msg.toString() + "' on a checksum replica."; 240 log.error(errMsg); 241 throw new IllegalState(errMsg); 242 } 243 244 /** 245 * This method is intended to retrieve a record from an arc-file within the archive. But since this handles checksum 246 * archive, it does not have the actual arc-files, and this function should therefore fail. 247 * 248 * @param msg The GetMessage for retrieving the arc-record from the archive. 249 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 250 * @throws ArgumentNotValid If the message is null. 251 */ 252 public void sendGetMessage(GetMessage msg) throws IllegalState, ArgumentNotValid { 253 ArgumentNotValid.checkNotNull(msg, "GetMessage msg"); 254 255 String errMsg = "A checksum replica cannot handle a GetMessage such as '" + msg + "'"; 256 log.error(errMsg); 257 throw new IllegalState(errMsg); 258 } 259 260 /** 261 * This method is intended to retrieve an arc-file from the archive. But since this handles checksum archive, it 262 * does not have the actual arc-files, and this function should therefore fail. 263 * 264 * @param gfm The GetFileMessage for retrieving the arc-file from the archive. 265 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 266 * @throws ArgumentNotValid If the message is null. 267 */ 268 public void sendGetFileMessage(GetFileMessage gfm) throws IllegalState, ArgumentNotValid { 269 ArgumentNotValid.checkNotNull(gfm, "GetFileMessage gfm"); 270 271 String errMsg = "A checksum replica cannot handle a GetFileMessage such as '" + gfm + "'."; 272 log.error(errMsg); 273 throw new IllegalState(errMsg); 274 } 275 276 /** 277 * This method is intended to retrieve an arc-file from the archive. But since this handles checksum archive, it 278 * does not have the actual arc-files, and this function should therefore fail. 279 * 280 * @param msg The RemoveAndGetFileMessage for removing and retrieving an arc-file from the archive. 281 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 282 * @throws ArgumentNotValid If the message is null. 283 */ 284 public void sendRemoveAndGetFileMessage(RemoveAndGetFileMessage msg) throws IllegalState, ArgumentNotValid { 285 ArgumentNotValid.checkNotNull(msg, "RemoveAndGetFileMessage msg"); 286 287 String errMsg = "A checksum replica cannot handle a RemoveAndGetFileMessage such as '" + msg + "'."; 288 log.error(errMsg); 289 throw new IllegalState(errMsg); 290 } 291 292 /** 293 * Method for closing this instance. 294 */ 295 public void close() { 296 log.debug("The ChecksumClient for replica '{}' has been shut down.", replicaId); 297 } 298 299}