![JAR search and dependency download from the Maven repository](/logo.png)
com.swiftmq.filetransfer.v940.FiletransferImpl Maven / Gradle / Ivy
/*
* Copyright 2019 IIT Software GmbH
*
* IIT Software GmbH licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.swiftmq.filetransfer.v940;
import com.swiftmq.filetransfer.*;
import com.swiftmq.filetransfer.protocol.MessageBasedFactory;
import com.swiftmq.filetransfer.protocol.v940.*;
import com.swiftmq.tools.requestreply.RequestRegistry;
import javax.jms.JMSException;
import javax.jms.Message;
import java.io.*;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class FiletransferImpl extends Filetransfer {
private static final String DEFAULT_DIGEST = "MD5";
JMSAccessorHolder accessorHolder = null;
File file = null;
String filename = null;
String link = null;
long expiration = 0;
int deleteAfterNumberDownloads = 0;
String password = null;
String passwordHexDigest = null;
boolean fileIsPrivate = false;
boolean useOriginalFilename = true;
File outputDir = null;
int chunkLength = 0;
String digestType = DEFAULT_DIGEST;
int replyInterval = 10;
Map properties = null;
String selector = null;
MessageBasedFactory messageBasedFactory = new ProtocolFactory();
boolean closed = false;
public FiletransferImpl(JMSAccessorHolder accessorHolder) {
this.accessorHolder = accessorHolder;
}
private void checkState() {
if (closed)
throw new IllegalStateException("This object has already been closed.");
}
public Filetransfer withFile(File file) {
checkState();
this.file = file;
return this;
}
public Filetransfer withFilename(String filename) {
checkState();
this.filename = filename;
return this;
}
public Filetransfer withLink(String link) {
checkState();
this.link = link;
return this;
}
public Filetransfer withDigestType(String digestType) {
checkState();
this.digestType = digestType;
return this;
}
public Filetransfer withDeleteAfterNumberDownloads(int deleteAfterNumberDownloads) {
checkState();
this.deleteAfterNumberDownloads = deleteAfterNumberDownloads;
return this;
}
public Filetransfer withExpiration(long expiration) {
checkState();
this.expiration = expiration;
return this;
}
public Filetransfer withPassword(String password) {
checkState();
this.password = password;
return this;
}
public Filetransfer withPasswordHexDigest(String passwordHexDigest) {
checkState();
this.passwordHexDigest = passwordHexDigest;
return this;
}
public Filetransfer withFileIsPrivate(boolean fileIsPrivate) {
checkState();
this.fileIsPrivate = fileIsPrivate;
return this;
}
public Filetransfer withOutputDirectory(File outputDir) {
checkState();
this.outputDir = outputDir;
return this;
}
public Filetransfer withOriginalFilename(boolean withOriginalFilename) {
checkState();
this.useOriginalFilename = withOriginalFilename;
return this;
}
public Filetransfer withProperties(Map properties) {
checkState();
this.properties = properties;
return this;
}
public Filetransfer withSelector(String selector) {
checkState();
this.selector = selector;
return this;
}
public Filetransfer withReplyInterval(int replyInterval) {
checkState();
this.replyInterval = replyInterval;
return this;
}
public String send() throws Exception {
return send(null);
}
public String send(ProgressListener progressListener) throws FiletransferException, JMSException, IOException, NoSuchAlgorithmException {
checkState();
if (file == null)
throw new NullPointerException("File is not specified");
if (!file.exists())
throw new FileNotFoundException("File not found");
if (file.isDirectory())
throw new FiletransferException("File to transfer is a directory");
if (file.length() == 0)
throw new FiletransferException("File to transfer is empty");
if (passwordHexDigest == null && password != null) {
byte[] pwdigest = MessageDigest.getInstance(digestType).digest(password.getBytes());
passwordHexDigest = Util.byteArrayToHexString(pwdigest);
}
FilePublishReply reply = (FilePublishReply) request(new FilePublishRequest(accessorHolder.replyQueue.getQueueName(), filename == null ? file.getName() : filename, accessorHolder.username, file.length(), expiration, deleteAfterNumberDownloads, digestType, passwordHexDigest, fileIsPrivate), accessorHolder, messageBasedFactory, properties);
if (!reply.isOk())
throw new FiletransferException(reply.getException());
String filename = file.getName();
chunkLength = reply.getChunkLength();
DigestInputStream digestInputStream = new DigestInputStream(new FileInputStream(file), MessageDigest.getInstance(digestType));
BufferedInputStream in = new BufferedInputStream(digestInputStream);
byte[] chunk = new byte[chunkLength];
int len = 0;
long cumulatedLen = 0;
long fileLength = file.length();
int chunkNo = 1;
String link = null;
while ((len = in.read(chunk)) != -1) {
cumulatedLen += len;
boolean last = cumulatedLen == fileLength;
boolean replyRequired = (chunkNo % replyInterval == 0) || last;
FileChunkReply chunkReply = (FileChunkReply) request(new FileChunkRequest(replyRequired, chunkNo, last, chunk, len), accessorHolder, messageBasedFactory);
if (replyRequired) {
if (chunkReply.isOk()) {
if (chunkReply.getChunkNo() != chunkNo)
throw new FiletransferException("Chunks no mismatch, sent: " + chunkNo + ", received: " + chunkReply.getChunkNo());
if (last) {
String linkString = chunkReply.getLink();
if (linkString == null)
throw new FiletransferException("No link returned on the last chunk");
link = linkString;
}
} else
throw new FiletransferException(reply.getException());
}
if (progressListener != null && replyRequired)
progressListener.progress(filename, chunkNo, fileLength, cumulatedLen, (int) (cumulatedLen * 100 / fileLength));
chunkNo++;
}
byte[] cacheDigest = new LinkParser(link).getDigest();
byte[] localDigest = digestInputStream.getMessageDigest().digest();
if (!Arrays.equals(localDigest, cacheDigest))
throw new FiletransferException("Cache digest is not equal to local digest");
return link;
}
public Filetransfer receive() throws FiletransferException, JMSException, IOException, NoSuchAlgorithmException {
return receive(null);
}
public Filetransfer receive(ProgressListener progressListener) throws FiletransferException, JMSException, IOException, NoSuchAlgorithmException {
checkState();
if (!useOriginalFilename && file == null)
throw new NullPointerException("File is not specified");
if (useOriginalFilename && outputDir == null)
throw new NullPointerException("Output directory is not specified");
if (link == null)
throw new NullPointerException("Link is not specified");
LinkParser linkParser = new LinkParser(link);
String pwdHexDigest = null;
if (password != null) {
byte[] pwdigest = MessageDigest.getInstance(linkParser.getDigestType()).digest(password.getBytes());
pwdHexDigest = Util.byteArrayToHexString(pwdigest);
}
FileConsumeReply reply = (FileConsumeReply) request(new FileConsumeRequest(accessorHolder.replyQueue.getQueueName(), link, pwdHexDigest, replyInterval), accessorHolder, messageBasedFactory, null);
if (!reply.isOk())
throw new FiletransferException(reply.getException());
if (useOriginalFilename)
file = new File(outputDir, reply.getFilename());
if (file.exists())
file.delete();
int currentInboundChunkNo = 0;
long cumulatedLen = 0;
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] localDigest = null;
DigestOutputStream digestOutputStream = new DigestOutputStream(new BufferedOutputStream(fileOutputStream, reply.getChunkLength()), MessageDigest.getInstance(linkParser.getDigestType()));
try {
for (; ; ) {
Message message = accessorHolder.consumer.receive(RequestRegistry.SWIFTMQ_REQUEST_TIMEOUT);
if (message == null)
throw new JMSException("Request timeout occured (" + RequestRegistry.SWIFTMQ_REQUEST_TIMEOUT + ") ms");
FileChunkRequest chunkRequest = (FileChunkRequest) messageBasedFactory.create(message);
if (chunkRequest.getChunkNo() != currentInboundChunkNo + 1)
throw new FiletransferException("ChunkNo out of order! Expecting " + (currentInboundChunkNo + 1) + " but was receiving " + chunkRequest.getChunkNo());
if (chunkRequest != null) {
byte[] chunk = chunkRequest.getChunk();
digestOutputStream.write(chunk);
digestOutputStream.flush();
cumulatedLen += chunk.length;
FileChunkReply chunkReply = null;
if (chunkRequest.isReplyRequired())
chunkReply = (FileChunkReply) chunkRequest.createReplyInstance();
if (chunkReply != null) {
chunkReply.setOk(true);
chunkReply.setChunkNo(chunkRequest.getChunkNo());
if (progressListener != null)
progressListener.progress(reply.getFilename(), chunkRequest.getChunkNo(), reply.getSize(), cumulatedLen, (int) (cumulatedLen * 100 / reply.getSize()));
}
currentInboundChunkNo = chunkRequest.getChunkNo();
if (chunkRequest.isLast()) {
fileOutputStream.getFD().sync();
localDigest = digestOutputStream.getMessageDigest().digest();
digestOutputStream.close();
byte[] cacheDigest = new LinkParser(link).getDigest();
if (!Arrays.equals(localDigest, cacheDigest)) {
chunkReply.setOk(false);
chunkReply.setException("Cache digest is not equal to local digest");
accessorHolder.producer.send(chunkReply.toMessage());
throw new FiletransferException("Cache digest is not equal to local digest");
} else {
chunkReply.setLink(new LinkBuilder(linkParser.getRouterName(), linkParser.getCacheName(), linkParser.getFileKey(), linkParser.getDigestType(), localDigest).toString());
accessorHolder.producer.send(chunkReply.toMessage());
}
break;
} else {
if (chunkReply != null)
accessorHolder.producer.send(chunkReply.toMessage());
}
}
}
} catch (JMSException | IOException | FiletransferException e) {
if (file.exists())
file.delete();
throw e;
}
return this;
}
public Filetransfer delete() throws FiletransferException, JMSException, IOException, NoSuchAlgorithmException {
checkState();
if (link == null)
throw new NullPointerException("Link is not specified");
LinkParser linkParser = new LinkParser(link);
String pwdHexDigest = null;
if (password != null) {
byte[] pwdigest = MessageDigest.getInstance(linkParser.getDigestType()).digest(password.getBytes());
pwdHexDigest = Util.byteArrayToHexString(pwdigest);
}
FileDeleteReply reply = (FileDeleteReply) request(new FileDeleteRequest(link, pwdHexDigest), accessorHolder, messageBasedFactory, null);
if (!reply.isOk())
throw new FiletransferException(reply.getException());
return this;
}
public List query() throws Exception {
checkState();
FileQueryReply reply = (FileQueryReply) request(new FileQueryRequest(selector), accessorHolder, messageBasedFactory, null);
if (!reply.isOk())
throw new FiletransferException(reply.getException());
return reply.getResult();
}
public Map> queryProperties() throws Exception {
throw new FiletransferException("Operation not supported, requires 9.4.1 at least!");
}
public void close() {
try {
request(new SessionCloseRequest(), accessorHolder, messageBasedFactory);
} catch (Exception e) {
}
try {
accessorHolder.producer.close();
} catch (JMSException e) {
}
try {
accessorHolder.consumer.close();
} catch (JMSException e) {
}
try {
accessorHolder.session.close();
} catch (JMSException e) {
}
try {
accessorHolder.replyQueue.delete();
} catch (JMSException e) {
}
closed = true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy