logEntry.logMessage("Received Pipe execution request", this, MessageLogger.DEBUG, requestTime);
}
// Get Source component and initialize its parameters
{
SourceIF source = getSource();
if(source == null) {
if(getSourceID() == null) {
logEntry.logMessage(
"Pipe does not have a Source component, aborting",
this,
MessageLogger.ERROR);
} else {
logEntry.logMessage(
"Pipe Source component cannot be loaded, aborting",
this,
MessageLogger.ERROR);
}
setExecutionEndInfo(new Date(), System.currentTimeMillis()-start, LogEntry.STATUS_SOURCE_ERROR);
addLogEntry(logEntry, LogEntry.STATUS_SOURCE_ERROR);
return;
}
source.setData(getSourceData());
}
// Get Converter components and initialize their parameters
{
int converterIndex = 0;
for(Iterator it = converterList.iterator(); it.hasNext();) {
ConverterListItem converterItem = (ConverterListItem) it.next();
converterIndex++;
try {
ConverterIF converter = converterItem.getConverter();
converter.setData(converterItem.getConverterData());
} catch(PipeComponentCreationException e) {
logEntry.logMessage("Pipe Converter component #" + converterIndex
+ " cannot be loaded, aborting", this, MessageLogger.ERROR);
Environment.getInstance().log("Error loading Converter component #" + converterIndex +
" for Pipe \"" + getName() + "\"", e);
setExecutionEndInfo(new Date(), System.currentTimeMillis()-start, LogEntry.STATUS_CONVERSION_ERROR);
addLogEntry(logEntry, LogEntry.STATUS_CONVERSION_ERROR);
return;
}
}
}
// Get Destination component and initialize its parameters
{
DestinationIF destination = getDestination();
if(destination == null) {
if(getDestinationID() == null) {
logEntry.logMessage(
"Pipe does not have a Destination component, aborting",
this,
MessageLogger.ERROR);
} else {
logEntry.logMessage(
"Pipe Destination component cannot be loaded, aborting",
this,
MessageLogger.ERROR);
}
setExecutionEndInfo(new Date(), System.currentTimeMillis()-start, LogEntry.STATUS_DESTINATION_ERROR);
addLogEntry(logEntry, LogEntry.STATUS_DESTINATION_ERROR);
return;
}
destination.setData(getDestinationData());
}
logEntry.logMessage("Starting Pipe execution", this, MessageLogger.DEBUG);
try {
/** Open Source, Converter and Destination components' sessions */
currentTask = "Pipe Component initialization";
statusCode = openComponentSessions(
source,
destination,
getConverterList(),
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,