/***************************************************************************
* Copyright (C) 2011 by Fabrizio Montesi <famontesi@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* For details about the authors of this software, see the AUTHORS file. *
***************************************************************************/
package jolie.process.courier;
import java.io.IOException;
import java.net.URISyntaxException;
import jolie.ExecutionThread;
import jolie.Interpreter;
import jolie.lang.Constants;
import jolie.net.CommChannel;
import jolie.net.CommMessage;
import jolie.net.ports.OutputPort;
import jolie.process.Process;
import jolie.process.TransformationReason;
import jolie.runtime.FaultException;
import jolie.runtime.Value;
import jolie.runtime.VariablePath;
import jolie.runtime.typing.OneWayTypeDescription;
import jolie.runtime.typing.TypeCheckingException;
/**
*
* @author Fabrizio Montesi
*/
public class ForwardNotificationProcess implements Process
{
private final String operationName;
private final OutputPort outputPort;
private final VariablePath outputVariablePath;
private final OneWayTypeDescription aggregatedTypeDescription, extenderTypeDescription;
public ForwardNotificationProcess(
String operationName,
OutputPort outputPort,
VariablePath outputVariablePath,
OneWayTypeDescription aggregatedTypeDescription,
OneWayTypeDescription extenderTypeDescription
) {
this.operationName = operationName;
this.outputPort = outputPort;
this.outputVariablePath = outputVariablePath;
this.aggregatedTypeDescription = aggregatedTypeDescription;
this.extenderTypeDescription = extenderTypeDescription;
}
public Process clone( TransformationReason reason )
{
return new ForwardNotificationProcess(
operationName,
outputPort,
outputVariablePath,
aggregatedTypeDescription,
extenderTypeDescription
);
}
private void log( String message )
{
Interpreter.getInstance().logInfo( "[Forward notification operation " + operationName + "@" + outputPort.id() + "]: " + message );
}
public void run()
throws FaultException
{
if ( ExecutionThread.currentThread().isKilled() ) {
return;
}
boolean verbose = Interpreter.getInstance().verbose();
CommChannel channel = null;
try {
Value messageValue = outputVariablePath.evaluate();
if ( extenderTypeDescription != null ) {
extenderTypeDescription.requestType().cutChildrenFromValue( messageValue );
}
aggregatedTypeDescription.requestType().check( messageValue );
CommMessage message = CommMessage.createRequest( operationName, outputPort.getResourcePath(), messageValue );
channel = outputPort.getCommChannel();
if ( verbose ) {
log( "sending request " + message.id() );
}
channel.send( message );
if ( verbose ) {
log( "request " + message.id() + " sent" );
}
CommMessage response = null;
do {
response = channel.recvResponseFor( message );
} while( response == null );
if ( verbose ) {
log( "received response for request " + response.id() );
}
if ( response.isFault() ) {
if ( response.fault().faultName().equals( "CorrelationError" )
|| response.fault().faultName().equals( "IOException" )
|| response.fault().faultName().equals( "TypeMismatch" )
) {
throw response.fault();
} else {
Interpreter.getInstance().logSevere( "Forward notification process for operation " + operationName + " received an unexpected fault: " + response.fault().faultName() );
}
}
} catch( IOException e ) {
throw new FaultException( Constants.IO_EXCEPTION_FAULT_NAME, e );
} catch( URISyntaxException e ) {
Interpreter.getInstance().logSevere( e );
} catch( TypeCheckingException e ) {
throw new FaultException( Constants.TYPE_MISMATCH_FAULT_NAME, "TypeMismatch (" + operationName + "@" + outputPort.id() + "): " + e.getMessage() );
} finally {
if ( channel != null ) {
try {
channel.release();
} catch( IOException e ) {
Interpreter.getInstance().logWarning( e );
}
}
}
}
public boolean isKillable()
{
return true;
}
}