46a022d86b
Build and Test j3270 / Build JAR & Run Tests (Java 21) (push) Successful in 42s
Build and Test j3270 / Build JAR & Run Tests (Java 17) (push) Successful in 1m9s
Release j3270 / Build & Publish Release (push) Successful in 32s
Build and Test j3270 / Build JAR & Run Tests (Java 11) (push) Successful in 42s
601 lines
24 KiB
Java
601 lines
24 KiB
Java
package haus.nightmare.lib3270j.xfer3270;
|
|
|
|
import haus.nightmare.lib3270j.charset.CodePage;
|
|
import haus.nightmare.lib3270j.charset.CodePageRegistry;
|
|
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
|
|
import haus.nightmare.lib3270j.datastream.DataStreamProcessor;
|
|
import haus.nightmare.lib3270j.ecl.*;
|
|
import haus.nightmare.lib3270j.ft.FTConfig;
|
|
import haus.nightmare.lib3270j.ft.FTConstants;
|
|
import haus.nightmare.lib3270j.ft.dir.CMSDirectoryEntry;
|
|
import haus.nightmare.lib3270j.ft.dir.CMSDirectoryParser;
|
|
import haus.nightmare.lib3270j.ft.dir.TSODirectoryEntry;
|
|
import haus.nightmare.lib3270j.ft.dir.TSODirectoryParser;
|
|
import haus.nightmare.lib3270j.input.InputProcessor;
|
|
import haus.nightmare.lib3270j.screen.ScreenBuffer;
|
|
import haus.nightmare.lib3270j.xfer.FileTransferHostDirectoryInterface;
|
|
import haus.nightmare.lib3270j.xfer.FileTransferInterface;
|
|
import haus.nightmare.lib3270j.xfer.FileTransferStatusInterface;
|
|
|
|
import java.net.URL;
|
|
import java.util.List;
|
|
import java.util.StringTokenizer;
|
|
import java.util.Vector;
|
|
import java.util.logging.Logger;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
/**
|
|
* Core 3270 File Transfer Controller conforming to Host On-Demand specifications.
|
|
*
|
|
* Implements FileTransferInterface and handles TSO/CMS/CICS IND$FILE options,
|
|
* dynamic MTU buffering, host/local dataset name mappings, directory queries,
|
|
* and Unicode transfer modes.
|
|
*/
|
|
public class Xfer3270 implements FileTransferInterface {
|
|
|
|
private static final Logger log = Logger.getLogger(Xfer3270.class.getName());
|
|
|
|
private static final Pattern RECFM_PATTERN = Pattern.compile("(?i)RECFM[\\s\\(]+([FVU]|FIXED|VARIABLE|UNDEFINED)\\)?");
|
|
private static final Pattern LRECL_PATTERN = Pattern.compile("(?i)LRECL[\\s\\(]+(\\d+)\\)?");
|
|
private static final Pattern BLK_PATTERN = Pattern.compile("(?i)(?:BLKSIZE|BLOCK)[\\s\\(]+(\\d+)\\)?");
|
|
private static final Pattern SPACE_PATTERN = Pattern.compile("(?i)SPACE[\\s\\(]+(\\d+)(?:[\\s,]+(\\d+))?\\)?");
|
|
private static final Pattern AVB_PATTERN = Pattern.compile("(?i)AVBLOCK[\\s\\(]+(\\d+)\\)?");
|
|
private static final Pattern MTU_PATTERN = Pattern.compile("(?i)(?:BUFFERSIZE|MTU|BUFSIZE)[\\s\\(]+(\\d+)\\)?");
|
|
|
|
public static final String UNICODE_UCS2_STR = "UCS2";
|
|
public static final String UNICODE_UTF8_STR = "UTF8";
|
|
public static final String UNICODE_UTF_8_STR = "UTF-8";
|
|
public static final int UNICODE_UCS2 = 0;
|
|
public static final int UNICODE_UTF8 = 1;
|
|
public static final String HOST_FILE_ERROR = "HOST_FILE_ERROR";
|
|
public static final int MIN_MTU_SIZE = 256;
|
|
public static final int MAX_MTU_SIZE = 32767;
|
|
public static final int DefaultUploadBufferSize = 2048;
|
|
|
|
// Session references
|
|
private ECLSession session;
|
|
private ScreenBuffer screen;
|
|
private InputProcessor input;
|
|
private DataStreamProcessor dsProcessor;
|
|
private EbcdicTranslator translator;
|
|
private CodePage currentCodePage;
|
|
private ECLXfer delegateXfer;
|
|
|
|
// State and Configuration
|
|
private int bmtuSize = 2500;
|
|
public int TimeOutValue = 30;
|
|
private long bytesTransferred = 0L;
|
|
private String sReasonTerminated = "";
|
|
private boolean bSendClear = true;
|
|
private boolean bCancelRequested = false;
|
|
|
|
// HoD Option Flags
|
|
public boolean option_ASCII = false;
|
|
public boolean option_SO = false;
|
|
public boolean option_NOSO = false;
|
|
public boolean option_BLANK = false;
|
|
public boolean option_USER = false;
|
|
public boolean option_APPEND = false;
|
|
public boolean option_NEW = false;
|
|
public boolean option_CRLF = false;
|
|
public boolean option_UNICODE = false;
|
|
public int unicodeType = UNICODE_UCS2;
|
|
|
|
// Mainframe dataset allocation parameters
|
|
private String recfm = "DEFAULT";
|
|
private int lrecl = 0;
|
|
private int blksize = 0;
|
|
private int primarySpace = 0;
|
|
private int secondarySpace = 0;
|
|
private String spaceUnits = "DEFAULT";
|
|
private int avblock = 0;
|
|
|
|
// Constructors
|
|
public Xfer3270() {
|
|
this.translator = new EbcdicTranslator();
|
|
this.currentCodePage = CodePageRegistry.getDefault();
|
|
}
|
|
|
|
public Xfer3270(ECLSession session) {
|
|
this(session, null);
|
|
}
|
|
|
|
public Xfer3270(ECLSession session, URL url) {
|
|
this.session = session;
|
|
if (session != null) {
|
|
this.delegateXfer = session.GetXfer();
|
|
}
|
|
this.translator = new EbcdicTranslator();
|
|
this.currentCodePage = CodePageRegistry.getDefault();
|
|
}
|
|
|
|
public Xfer3270(ECLXfer xfer) {
|
|
this.delegateXfer = xfer;
|
|
this.translator = new EbcdicTranslator();
|
|
this.currentCodePage = CodePageRegistry.getDefault();
|
|
}
|
|
|
|
public Xfer3270(ScreenBuffer screen, InputProcessor input,
|
|
DataStreamProcessor dsProcessor, CodePage codePage) {
|
|
this.screen = screen;
|
|
this.input = input;
|
|
this.dsProcessor = dsProcessor;
|
|
this.currentCodePage = codePage != null ? codePage : CodePageRegistry.getDefault();
|
|
this.translator = new EbcdicTranslator(this.currentCodePage.getCodePageId());
|
|
this.delegateXfer = new ECLXfer(screen, input, dsProcessor, translator);
|
|
}
|
|
|
|
// ========== Option Flags Parser ==========
|
|
|
|
/**
|
|
* Parses TSO and VM option flags into internal state, conforming to HoD syntax.
|
|
* @param options Option flags string
|
|
*/
|
|
public void setOptionFlags(String options) {
|
|
this.option_ASCII = false;
|
|
this.option_SO = false;
|
|
this.option_NOSO = false;
|
|
this.option_BLANK = false;
|
|
this.option_USER = false;
|
|
this.option_APPEND = false;
|
|
this.option_NEW = false;
|
|
this.option_CRLF = false;
|
|
this.option_UNICODE = false;
|
|
this.unicodeType = UNICODE_UCS2;
|
|
this.recfm = "DEFAULT";
|
|
this.lrecl = 0;
|
|
this.blksize = 0;
|
|
this.primarySpace = 0;
|
|
this.secondarySpace = 0;
|
|
this.spaceUnits = "DEFAULT";
|
|
this.avblock = 0;
|
|
|
|
if (options == null || options.trim().isEmpty()) return;
|
|
String upper = options.toUpperCase();
|
|
|
|
if (upper.contains("ASCII")) this.option_ASCII = true;
|
|
if (upper.contains(" SO") || upper.contains("(SO")) this.option_SO = true;
|
|
if (upper.contains("NOSO")) this.option_NOSO = true;
|
|
if (upper.contains("BLANK")) this.option_BLANK = true;
|
|
if (upper.contains("USER")) this.option_USER = true;
|
|
if (upper.contains("APPEND")) this.option_APPEND = true;
|
|
if (upper.contains("NEW")) this.option_NEW = true;
|
|
if (upper.contains("CRLF") && !upper.contains("NOCRLF")) this.option_CRLF = true;
|
|
|
|
// UNICODE options: UNICODE or UNICODE(UTF-8) / UNICODE(UCS2)
|
|
int uIdx = upper.indexOf("UNICODE");
|
|
if (uIdx > -1) {
|
|
this.option_UNICODE = true;
|
|
int pStart = upper.indexOf('(', uIdx);
|
|
int pEnd = upper.indexOf(')', uIdx);
|
|
String uSub = "";
|
|
if (pStart > uIdx && pEnd > pStart) {
|
|
uSub = upper.substring(pStart + 1, pEnd);
|
|
}
|
|
if (uSub.contains(UNICODE_UTF8_STR) || uSub.contains(UNICODE_UTF_8_STR)) {
|
|
this.unicodeType = UNICODE_UTF8;
|
|
} else {
|
|
this.unicodeType = UNICODE_UCS2;
|
|
}
|
|
}
|
|
|
|
// Mainframe dataset parameters
|
|
Matcher recfmMatcher = RECFM_PATTERN.matcher(options);
|
|
if (recfmMatcher.find()) this.recfm = recfmMatcher.group(1).toUpperCase();
|
|
|
|
Matcher lreclMatcher = LRECL_PATTERN.matcher(options);
|
|
if (lreclMatcher.find()) {
|
|
try { this.lrecl = Integer.parseInt(lreclMatcher.group(1)); } catch (NumberFormatException ignored) {}
|
|
}
|
|
|
|
Matcher blkMatcher = BLK_PATTERN.matcher(options);
|
|
if (blkMatcher.find()) {
|
|
try { this.blksize = Integer.parseInt(blkMatcher.group(1)); } catch (NumberFormatException ignored) {}
|
|
}
|
|
|
|
Matcher spaceMatcher = SPACE_PATTERN.matcher(options);
|
|
if (spaceMatcher.find()) {
|
|
try {
|
|
this.primarySpace = Integer.parseInt(spaceMatcher.group(1));
|
|
if (spaceMatcher.group(2) != null) {
|
|
this.secondarySpace = Integer.parseInt(spaceMatcher.group(2));
|
|
}
|
|
} catch (NumberFormatException ignored) {}
|
|
}
|
|
|
|
Matcher avbMatcher = AVB_PATTERN.matcher(options);
|
|
if (avbMatcher.find()) {
|
|
try {
|
|
this.avblock = Integer.parseInt(avbMatcher.group(1));
|
|
this.spaceUnits = "AVBLOCK";
|
|
} catch (NumberFormatException ignored) {}
|
|
}
|
|
|
|
if (upper.contains("TRACKS") || upper.contains("TRK")) {
|
|
this.spaceUnits = "TRACKS";
|
|
} else if (upper.contains("CYLINDERS") || upper.contains("CYL")) {
|
|
this.spaceUnits = "CYLINDERS";
|
|
}
|
|
|
|
Matcher mtuMatcher = MTU_PATTERN.matcher(options);
|
|
if (mtuMatcher.find()) {
|
|
try {
|
|
SetMTUSize(Integer.parseInt(mtuMatcher.group(1)));
|
|
} catch (NumberFormatException ignored) {}
|
|
}
|
|
}
|
|
|
|
// ========== File Name Formatting ==========
|
|
|
|
@Override
|
|
public String getHostFileName(String string, int n) {
|
|
if (string == null) return n == VM_CMS ? "NONE NONE" : "";
|
|
String trimmed = string.trim();
|
|
if (trimmed.isEmpty()) {
|
|
return n == VM_CMS ? "NONE NONE" : "";
|
|
}
|
|
String result = "";
|
|
StringTokenizer st = new StringTokenizer(trimmed, ". \t");
|
|
|
|
switch (n) {
|
|
case VM_CMS: { // 0
|
|
String fn = st.hasMoreTokens() ? st.nextToken() : "";
|
|
String ft = st.hasMoreTokens() ? st.nextToken() : "";
|
|
if (fn.length() > 8) fn = fn.substring(0, 8);
|
|
if (ft.length() > 8) ft = ft.substring(0, 8);
|
|
if (fn.isEmpty()) fn = "NONE";
|
|
if (ft.isEmpty()) ft = "NONE";
|
|
result = fn + " " + ft;
|
|
break;
|
|
}
|
|
case MVS_TSO: { // 1
|
|
StringBuilder sb = new StringBuilder();
|
|
while (st.hasMoreTokens()) {
|
|
String token = st.nextToken();
|
|
if (token.length() > 8) token = token.substring(0, 8);
|
|
if (sb.length() > 0) sb.append(".");
|
|
sb.append(token);
|
|
}
|
|
result = sb.toString();
|
|
break;
|
|
}
|
|
case CICS: { // 2
|
|
String token = st.nextToken();
|
|
result = token.length() > 8 ? token.substring(0, 8) : token;
|
|
break;
|
|
}
|
|
default:
|
|
result = string.trim();
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public String getLocalFileName(String string, int n) {
|
|
if (string == null || string.trim().isEmpty()) return "";
|
|
String trimmed = string.trim();
|
|
String result = "";
|
|
|
|
switch (n) {
|
|
case VM_CMS: { // 0
|
|
StringTokenizer st = new StringTokenizer(trimmed, " ");
|
|
String fn = st.hasMoreTokens() ? st.nextToken() : "NONE";
|
|
String ft = st.hasMoreTokens() ? st.nextToken() : "NONE";
|
|
result = fn + "." + ft;
|
|
break;
|
|
}
|
|
case MVS_TSO: { // 1
|
|
if (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length() >= 2) {
|
|
result = trimmed.substring(1, trimmed.length() - 1);
|
|
} else {
|
|
result = trimmed;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
result = trimmed;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// ========== State Inspection ==========
|
|
|
|
public String stateIs(int n) {
|
|
switch (n) {
|
|
case 0: return "Idle";
|
|
case 1: return "W4DirectoryList";
|
|
case 2: return "W4GetFile";
|
|
case 3: return "W4PutFile";
|
|
case 12: return "W4Data";
|
|
case 19: return "UploadComplete";
|
|
case 20: return "DnloadComplete";
|
|
case 21: return "Quiting";
|
|
default: return "Unknown (" + n + ")";
|
|
}
|
|
}
|
|
|
|
public boolean isTransferActive() {
|
|
return delegateXfer != null && delegateXfer.isTransferActive();
|
|
}
|
|
|
|
public long getBytesTransferred() {
|
|
if (delegateXfer != null) return delegateXfer.getBytesTransferred();
|
|
return bytesTransferred;
|
|
}
|
|
|
|
// ========== Buffer / MTU Management ==========
|
|
|
|
public void SetMTUSize(int n) {
|
|
if (n < MIN_MTU_SIZE) n = MIN_MTU_SIZE;
|
|
if (n > MAX_MTU_SIZE) n = MAX_MTU_SIZE;
|
|
this.bmtuSize = n;
|
|
if (delegateXfer != null) {
|
|
delegateXfer.setMTUSize(this.bmtuSize);
|
|
}
|
|
}
|
|
|
|
public int GetMTUSize() {
|
|
if (delegateXfer != null) return delegateXfer.getMTUSize();
|
|
return bmtuSize;
|
|
}
|
|
|
|
public void setMTUSize(int n) { SetMTUSize(n); }
|
|
public int getMTUSize() { return GetMTUSize(); }
|
|
|
|
public void setClear(boolean bl) {
|
|
this.bSendClear = bl;
|
|
}
|
|
|
|
public void resendInboundDataBufferToHost() {
|
|
if (delegateXfer != null) {
|
|
delegateXfer.resendInboundDataBufferToHost();
|
|
}
|
|
}
|
|
|
|
// ========== File Transfer Operations ==========
|
|
|
|
@Override
|
|
public void getFile(String hostFile, int hostType, String localFile, int transferMode,
|
|
FileTransferStatusInterface status, String options) throws ECLErr {
|
|
setOptionFlags(options);
|
|
if (transferMode == BINARY) {
|
|
this.option_ASCII = false;
|
|
} else {
|
|
this.option_ASCII = true;
|
|
}
|
|
|
|
FTConfig config = new FTConfig();
|
|
config.setDirection(FTConfig.Direction.RECEIVE);
|
|
config.setLocalFilename(localFile);
|
|
config.setHostFilename(hostFile);
|
|
config.setHostType(hostType == VM_CMS ? FTConfig.HostType.CMS :
|
|
(hostType == CICS ? FTConfig.HostType.CICS : FTConfig.HostType.TSO));
|
|
config.setTransferMode(this.option_ASCII ? FTConfig.TransferMode.ASCII : FTConfig.TransferMode.BINARY);
|
|
config.setCrAction(this.option_CRLF ? FTConfig.CrAction.REMOVE : FTConfig.CrAction.KEEP);
|
|
config.setExistAction(this.option_APPEND ? FTConfig.ExistAction.APPEND : FTConfig.ExistAction.REPLACE);
|
|
config.setDftBufferSize(bmtuSize);
|
|
if (options != null && !options.isEmpty()) {
|
|
config.parseOptions(options);
|
|
}
|
|
|
|
executeTransfer(config, status, localFile, hostFile);
|
|
}
|
|
|
|
public void getFile(String command, String hostFile, String localFile, int mode,
|
|
String options, ECLXferListener listener) throws ECLErr {
|
|
FileTransferStatusInterface statusAdapter = createStatusAdapter(listener, localFile, hostFile);
|
|
getFile(hostFile, MVS_TSO, localFile, mode, statusAdapter, options);
|
|
}
|
|
|
|
@Override
|
|
public void putFile(String localFile, int hostType, String hostFile, int transferMode,
|
|
FileTransferStatusInterface status, String options) throws ECLErr {
|
|
setOptionFlags(options);
|
|
if (transferMode == BINARY) {
|
|
this.option_ASCII = false;
|
|
} else {
|
|
this.option_ASCII = true;
|
|
}
|
|
|
|
FTConfig config = new FTConfig();
|
|
config.setDirection(FTConfig.Direction.SEND);
|
|
config.setLocalFilename(localFile);
|
|
config.setHostFilename(hostFile);
|
|
config.setHostType(hostType == VM_CMS ? FTConfig.HostType.CMS :
|
|
(hostType == CICS ? FTConfig.HostType.CICS : FTConfig.HostType.TSO));
|
|
config.setTransferMode(this.option_ASCII ? FTConfig.TransferMode.ASCII : FTConfig.TransferMode.BINARY);
|
|
config.setCrAction(this.option_CRLF ? FTConfig.CrAction.REMOVE : FTConfig.CrAction.KEEP);
|
|
config.setRecfm(recfm);
|
|
config.setLrecl(String.valueOf(lrecl));
|
|
config.setBlksize(String.valueOf(blksize));
|
|
config.setDftBufferSize(bmtuSize);
|
|
if (primarySpace > 0) {
|
|
config.setSpace(primarySpace + (secondarySpace > 0 ? "," + secondarySpace : ""));
|
|
}
|
|
if ("TRACKS".equalsIgnoreCase(spaceUnits)) config.setUnits(FTConfig.AllocationUnit.TRACKS);
|
|
else if ("CYLINDERS".equalsIgnoreCase(spaceUnits)) config.setUnits(FTConfig.AllocationUnit.CYLINDERS);
|
|
else if ("AVBLOCK".equalsIgnoreCase(spaceUnits)) config.setUnits(FTConfig.AllocationUnit.AVBLOCK);
|
|
|
|
if (options != null && !options.isEmpty()) {
|
|
config.parseOptions(options);
|
|
}
|
|
|
|
executeTransfer(config, status, localFile, hostFile);
|
|
}
|
|
|
|
public void putFile(String command, String hostFile, String localFile, int mode,
|
|
String options, ECLXferListener listener) throws ECLErr {
|
|
FileTransferStatusInterface statusAdapter = createStatusAdapter(listener, localFile, hostFile);
|
|
putFile(localFile, MVS_TSO, hostFile, mode, statusAdapter, options);
|
|
}
|
|
|
|
private void executeTransfer(FTConfig config, FileTransferStatusInterface status,
|
|
String locFile, String hstFile) throws ECLErr {
|
|
if (delegateXfer == null) {
|
|
throw new ECLErr("Xfer3270", "ECL0148", "Session or ECLXfer delegate not initialized");
|
|
}
|
|
|
|
if (status != null) {
|
|
java.io.File f = new java.io.File(locFile);
|
|
status.setFileInfo(locFile, f.exists() ? f.length() : -1L);
|
|
status.startTransfer();
|
|
}
|
|
|
|
ECLXferListener transferListener = new ECLXferListener() {
|
|
@Override
|
|
public void xferEvent(ECLXferEvent event) {
|
|
if (status == null) return;
|
|
long bytes = event.getBytesTransferred();
|
|
bytesTransferred = bytes;
|
|
status.bytesTransfered(bytes);
|
|
long total = event.getTotalBytes();
|
|
int pct = (total > 0) ? (int) ((bytes * 100) / total) : -1;
|
|
status.onProgress(bytes, total, pct);
|
|
|
|
if (event.isCompleted()) {
|
|
status.transferComplete();
|
|
} else if (event.isAborted()) {
|
|
sReasonTerminated = event.getMessage();
|
|
}
|
|
}
|
|
};
|
|
|
|
delegateXfer.addXferListener(transferListener);
|
|
try {
|
|
int rc;
|
|
if (config.isReceive()) {
|
|
rc = delegateXfer.ReceiveFile(config.getLocalFilename(), config.getHostFilename(), config.buildCommand());
|
|
} else {
|
|
rc = delegateXfer.SendFile(config.getLocalFilename(), config.getHostFilename(), config.buildCommand());
|
|
}
|
|
if (rc != 0) {
|
|
throw new ECLErr("Xfer3270", "ECL0150", "Transfer initiation failed with code " + rc);
|
|
}
|
|
} finally {
|
|
delegateXfer.removeXferListener(transferListener);
|
|
}
|
|
}
|
|
|
|
private FileTransferStatusInterface createStatusAdapter(ECLXferListener listener, String loc, String hst) {
|
|
if (listener == null) return null;
|
|
return new FileTransferStatusInterface() {
|
|
@Override
|
|
public void setFileInfo(String name, long size) {
|
|
listener.xferEvent(new ECLXferEvent(Xfer3270.this, ECLXferEvent.XFER_STARTED, 0, size, 0, "Transfer initiated", loc, hst));
|
|
}
|
|
|
|
@Override
|
|
public void startTransfer() {
|
|
listener.xferEvent(new ECLXferEvent(Xfer3270.this, ECLXferEvent.XFER_STARTED, 0, 0, 0, "Transfer started", loc, hst));
|
|
}
|
|
|
|
@Override
|
|
public void bytesTransfered(long bytes) {
|
|
listener.xferEvent(new ECLXferEvent(Xfer3270.this, ECLXferEvent.XFER_PROGRESS, bytes, 0, 0, bytes + " bytes transferred", loc, hst));
|
|
}
|
|
|
|
@Override
|
|
public void transferComplete() {
|
|
listener.xferEvent(new ECLXferEvent(Xfer3270.this, ECLXferEvent.XFER_COMPLETED, bytesTransferred, 0, 0, "Transfer complete", loc, hst));
|
|
}
|
|
};
|
|
}
|
|
|
|
// ========== Directory Query Operations ==========
|
|
|
|
@Override
|
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
public Vector getFiles(String hostQuery, int hostType, int timeout,
|
|
Vector localFiles, Vector hostFiles,
|
|
FileTransferHostDirectoryInterface callback) throws ECLErr {
|
|
if (callback != null) callback.setStatus(FileTransferHostDirectoryInterface.STATUS_PROCESSING);
|
|
Vector result = new Vector();
|
|
|
|
try {
|
|
if (hostType == VM_CMS) {
|
|
if (callback != null) callback.setStatus(FileTransferHostDirectoryInterface.STATUS_RECEIVING);
|
|
List<CMSDirectoryEntry> cmsEntries = CMSDirectoryParser.parse(hostQuery);
|
|
for (CMSDirectoryEntry entry : cmsEntries) {
|
|
String hName = entry.getFilename() + " " + entry.getFiletype();
|
|
String lName = entry.getFilename() + "." + entry.getFiletype();
|
|
if (hostFiles != null) hostFiles.addElement(hName);
|
|
if (localFiles != null) localFiles.addElement(lName);
|
|
result.addElement(entry);
|
|
}
|
|
if (callback != null) {
|
|
callback.onDirectoryLoaded(cmsEntries);
|
|
callback.setStatus(cmsEntries.isEmpty() ?
|
|
FileTransferHostDirectoryInterface.STATUS_EMPTY :
|
|
FileTransferHostDirectoryInterface.STATUS_OK);
|
|
}
|
|
} else {
|
|
if (callback != null) callback.setStatus(FileTransferHostDirectoryInterface.STATUS_RECEIVING);
|
|
List<TSODirectoryEntry> tsoEntries = TSODirectoryParser.parse(hostQuery);
|
|
for (TSODirectoryEntry entry : tsoEntries) {
|
|
String name = entry.getName();
|
|
if (hostFiles != null) hostFiles.addElement(name);
|
|
if (localFiles != null) localFiles.addElement(name);
|
|
result.addElement(entry);
|
|
}
|
|
if (callback != null) {
|
|
callback.onDirectoryLoaded(tsoEntries);
|
|
callback.setStatus(tsoEntries.isEmpty() ?
|
|
FileTransferHostDirectoryInterface.STATUS_EMPTY :
|
|
FileTransferHostDirectoryInterface.STATUS_OK);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
if (callback != null) {
|
|
callback.onDirectoryError(e.getMessage());
|
|
callback.setStatus(FileTransferHostDirectoryInterface.STATUS_EMPTY);
|
|
}
|
|
throw new ECLErr("Xfer3270", "ECL0149", "Directory retrieval failed: " + e.getMessage());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public void cancelTransfer() {
|
|
this.bCancelRequested = true;
|
|
if (delegateXfer != null) {
|
|
delegateXfer.cancelTransfer();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setCodePage(CodePage codePage) {
|
|
this.currentCodePage = codePage;
|
|
if (delegateXfer != null && codePage != null) {
|
|
if (translator != null) {
|
|
translator.setCodePage(codePage.getCodePageId());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setCodePage(String codePageName) {
|
|
CodePage cp = CodePageRegistry.get(codePageName);
|
|
if (cp != null) {
|
|
setCodePage(cp);
|
|
} else if (translator != null) {
|
|
translator.setCodePage(codePageName);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getErrorMessage(Exception ex) {
|
|
if (ex != null && ex.getMessage() != null && !ex.getMessage().isEmpty()) {
|
|
return ex.getMessage();
|
|
}
|
|
return sReasonTerminated.isEmpty() ? "Unknown file transfer error" : sReasonTerminated;
|
|
}
|
|
|
|
public ECLXfer getDelegateXfer() {
|
|
return delegateXfer;
|
|
}
|
|
}
|