info,
logEntry);
if(statusCode != LogEntry.STATUS_OK) {
// Initialization failed, LogEntry's statusCode is used at the end of this method
// for addLogEntry() call
throw new FailTransferException();
}
componentSessionsOpen = true;
/** Pipe iteration loop starts here */
int i = 0;
while(true) {
try {
logEntry.logMessage(
"Requesting data block #" + ++i + " from Source component",
this,
MessageLogger.DEBUG);
currentTask = "Source component " + this.source.getName();
statusCode = LogEntry.STATUS_SOURCE_ERROR;
String sourceResults[] = source.give(info, logEntry);
// Test if Source component returned no (more) data
if(sourceResults == null || sourceResults[0] == null) {
logEntry.logMessage(
"Source component returned no data",
this,
MessageLogger.DEBUG);
/*
* Exit iteration loop when Source component returns null instead of data
* String
*/
break;
}
if(sourceResults.length > 1) {
logEntry.logMessage("Source component returned " + sourceResults.length
+ " data blocks", this, MessageLogger.DEBUG);
}
// Iterate over Strings returned by Source component
for(int j = 0; j < sourceResults.length; j++) {
// Proceed with conversions
statusCode = LogEntry.STATUS_CONVERSION_ERROR;
currentTask = "Preparing to call first Converter component";
getConverterList();
Iterator it = this.converterList.iterator();
// Check if we have any Converters on the list
if(it.hasNext() == true) {
/*
* Converters (such as SplitConverter) may return multiple data parts
* based on a single input String
*/
String[] processedData = new String[1];
/*
* For first Converter on the list we call the regular 'convert' method,
* which takes String as input and returns String array
*/
ConverterListItem converterItem = (ConverterListItem) it.next();
ConverterIF converter = converterItem.getConverter();
currentTask = "Converter component " + converter.getName();
processedData = converter.convert(sourceResults[j], info, logEntry);
/*
* Test if any of the first Converter's result Strings is null, if yes ->
* report an error and abort Pipe execution
*/
if(arrayContainsNull(processedData)) {
logEntry.logMessage(
"Error: Converter " + converter.getName()
+ " returned null result, aborting",
this,
MessageLogger.ERROR);
throw new FailTransferException();
}
/*
* Repeat over the rest of the Converters list and call 'convertAll'
* method for processing every String in a String array
*/
while(it.hasNext()) {
converterItem = (ConverterListItem) it.next();
converter = converterItem.getConverter();
currentTask = "Converter component " + converter.getName();
processedData = converter.convertAll(processedData, info, logEntry);
/*
* Test if any of the Converter's result Strings is null, if yes ->
* report an error and abort Pipe execution
*/
if(arrayContainsNull(processedData)) {
logEntry.logMessage(
"Error: Converter " + converter.getName()
+ " returned null result, aborting",
this,
MessageLogger.ERROR);
throw new FailTransferException();
}
}
statusCode = LogEntry.STATUS_DESTINATION_ERROR;
currentTask = "Destination component " + this.destination.getName();
destination.takeAll(processedData, info, logEntry);
} else {
/*
* There were no Converters in this Pipe, so we pass the data from
* Source component directly to Destination component
*/
statusCode = LogEntry.STATUS_DESTINATION_ERROR;
currentTask = "Destination component " + this.destination.getName();
destination.take(sourceResults[j], info, logEntry);
}
statusCode = LogEntry.STATUS_OK;
}
/*
* Notify the Source component that last data block(s) were processed
* successfully
*/
statusCode = LogEntry.STATUS_SOURCE_ERROR;
currentTask = "while notifying Source component " + this.source.getName() + " of "
+ " successful processing of last data block through the Pipe";
source.lastBlockStatus(PIPE_EXECUTION_OK);
currentTask = "End of Pipe iteration loop";
statusCode = LogEntry.STATUS_OK;
} catch(AbortTransferException ate) {
/*
* Pass on AbortTransferException to the outside-loop catcher, since we want to
* abort the entire transfer.
*/
throw ate;
} catch(Throwable t) {
if(t instanceof Exception || t instanceof VirtualMachineError) {
logPipeExecutionError(t, currentTask, logEntry);
/**
* Notify the Source component of last data block failing to process, unless
* an unknown exception has occured in the Source component itself
*/
if(statusCode != LogEntry.STATUS_SOURCE_ERROR) {
currentTask = "Notifying Source component " + this.source.getName()
+ " of last data block failing to process through the Pipe";
// TODO: test support for FailTransferException and AbortTransferException during lastBlockStatus!
source.lastBlockStatus(PIPE_EXECUTION_FAILED);
}
logEntry.logMessage(
"Data block processing failed, aborting Pipe execution",
this,
MessageLogger.ERROR);
if(t instanceof Exception) {
// Pass Exception for the outer Exception handler
throw (Exception) t;
} else {
// Convert VirtualMachineErrors to FailTransferExceptions as we have
// already written the detailed error message to Transfer log
throw new FailTransferException();
}
}
}