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 * @throws ArgumentNotValid If the remote file is null. 192 */ 193 public void sendUploadMessage(RemoteFile rf) throws ArgumentNotValid { 194 // validate arguments. 195 ArgumentNotValid.checkNotNull(rf, "RemoteFile rf"); 196 197 // create and send message. 198 UploadMessage up = new UploadMessage(theChecksumChannel, Channels.getTheRepos(), rf); 199 jmsCon.send(up); 200 201 // log message 202 log.debug("Sending upload message '{}'.", up.toString()); 203 } 204 205 /** 206 * Method for sending batch job messages to the replica. This is not allowed since this archive at the end of this 207 * client is a checksum archive, which cannot handle batch jobs. 208 * 209 * @param replyChannel The channel where the reply should be sent. 210 * @param job The batchjob to execute. 211 * @return Nothing. It always throws an exception, since it is not allowed to run batchjobs on a checksum archive. 212 * @throws IllegalState Always. Since it is not legal to send a batchjob to a checksum replica. 213 * @throws ArgumentNotValid If the channel or the batchjob is null. 214 */ 215 public BatchMessage sendBatchJob(ChannelID replyChannel, FileBatchJob job) throws IllegalState, ArgumentNotValid { 216 ArgumentNotValid.checkNotNull(replyChannel, "ChannelID replyChannel"); 217 ArgumentNotValid.checkNotNull(job, "FileBatchJob job"); 218 219 String errMsg = "Trying to execute the batchjob '" + job.getClass().getName() + "'" 220 + " on a checksum replica with reply " + "channel '" + replyChannel + "'. This is not allowed!"; 221 log.error(errMsg); 222 throw new IllegalState(errMsg); 223 } 224 225 /** 226 * Method for sending batch job messages to the replica. This is not allowed since this archive at the end of this 227 * client is a checksum archive, which cannot handle batch jobs. 228 * 229 * @param msg The batch message. 230 * @return Nothing. It always throws an exception, since it is not allowed to run batchjobs on a checksum archive. 231 * @throws IllegalState Always. Since it is not legal to send a batchjob to a checksum replica. 232 * @throws ArgumentNotValid If the message is null. 233 */ 234 public BatchMessage sendBatchJob(BatchMessage msg) throws IllegalState, ArgumentNotValid { 235 ArgumentNotValid.checkNotNull(msg, "BatchMessage msg"); 236 237 String errMsg = "Trying to execute the batchjob '" + msg.toString() + "' on a checksum replica."; 238 log.error(errMsg); 239 throw new IllegalState(errMsg); 240 } 241 242 /** 243 * This method is intended to retrieve a record from an arc-file within the archive. But since this handles checksum 244 * archive, it does not have the actual arc-files, and this function should therefore fail. 245 * 246 * @param msg The GetMessage for retrieving the arc-record from the archive. 247 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 248 * @throws ArgumentNotValid If the message is null. 249 */ 250 public void sendGetMessage(GetMessage msg) throws IllegalState, ArgumentNotValid { 251 ArgumentNotValid.checkNotNull(msg, "GetMessage msg"); 252 253 String errMsg = "A checksum replica cannot handle a GetMessage such as '" + msg + "'"; 254 log.error(errMsg); 255 throw new IllegalState(errMsg); 256 } 257 258 /** 259 * This method is intended to retrieve an arc-file from the archive. But since this handles checksum archive, it 260 * does not have the actual arc-files, and this function should therefore fail. 261 * 262 * @param gfm The GetFileMessage for retrieving the arc-file from the archive. 263 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 264 * @throws ArgumentNotValid If the message is null. 265 */ 266 public void sendGetFileMessage(GetFileMessage gfm) throws IllegalState, ArgumentNotValid { 267 ArgumentNotValid.checkNotNull(gfm, "GetFileMessage gfm"); 268 269 String errMsg = "A checksum replica cannot handle a GetFileMessage such as '" + gfm + "'."; 270 log.error(errMsg); 271 throw new IllegalState(errMsg); 272 } 273 274 /** 275 * This method is intended to retrieve an arc-file from the archive. But since this handles checksum archive, it 276 * does not have the actual arc-files, and this function should therefore fail. 277 * 278 * @param msg The RemoveAndGetFileMessage for removing and retrieving an arc-file from the archive. 279 * @throws IllegalState Always. Since checksum replicas cannot handle this kind of messages. 280 * @throws ArgumentNotValid If the message is null. 281 */ 282 public void sendRemoveAndGetFileMessage(RemoveAndGetFileMessage msg) throws IllegalState, ArgumentNotValid { 283 ArgumentNotValid.checkNotNull(msg, "RemoveAndGetFileMessage msg"); 284 285 String errMsg = "A checksum replica cannot handle a RemoveAndGetFileMessage such as '" + msg + "'."; 286 log.error(errMsg); 287 throw new IllegalState(errMsg); 288 } 289 290 /** 291 * Method for closing this instance. 292 */ 293 public void close() { 294 log.debug("The ChecksumClient for replica '{}' has been shut down.", replicaId); 295 } 296 297}