/*************************************************************************** * 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.ExitingException; import jolie.runtime.FaultException; import jolie.runtime.Value; import jolie.runtime.VariablePath; import jolie.runtime.typing.RequestResponseTypeDescription; import jolie.runtime.typing.Type; import jolie.runtime.typing.TypeCheckingException; /** * * @author Fabrizio Montesi */ public class ForwardSolicitResponseProcess implements Process { private final String operationName; private final OutputPort outputPort; private final VariablePath outputVariablePath, inputVariablePath; private final RequestResponseTypeDescription aggregatedTypeDescription, extenderTypeDescription; public ForwardSolicitResponseProcess( String operationName, OutputPort outputPort, VariablePath outputVariablePath, VariablePath inputVariablePath, RequestResponseTypeDescription aggregatedTypeDescription, RequestResponseTypeDescription extenderTypeDescription ) { this.operationName = operationName; this.outputPort = outputPort; this.outputVariablePath = outputVariablePath; this.inputVariablePath = inputVariablePath; this.aggregatedTypeDescription = aggregatedTypeDescription; this.extenderTypeDescription = extenderTypeDescription; } public Process clone( TransformationReason reason ) { return new ForwardSolicitResponseProcess( operationName, outputPort, outputVariablePath, inputVariablePath, aggregatedTypeDescription, extenderTypeDescription ); } private void log( String message ) { Interpreter.getInstance().logInfo( "[Forward solicit-response 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 ); //channel.release(); TODO release channel if possible (i.e. it will not be closed) 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 ( inputVariablePath != null ) { inputVariablePath.setValue( response.value() ); } if ( response.isFault() ) { Type faultType = aggregatedTypeDescription.getFaultType( response.fault().faultName() ); if ( faultType != null ) { try { faultType.check( response.fault().value() ); } catch( TypeCheckingException e ) { throw new FaultException( Constants.TYPE_MISMATCH_FAULT_NAME, "Received fault " + response.fault().faultName() + " TypeMismatch (" + operationName + "@" + outputPort.id() + "): " + e.getMessage() ); } } throw response.fault(); } else { if ( aggregatedTypeDescription.responseType() != null ) { try { aggregatedTypeDescription.responseType().check( response.value() ); } catch( TypeCheckingException e ) { throw new FaultException( Constants.TYPE_MISMATCH_FAULT_NAME, "Received message TypeMismatch (" + operationName + "@" + outputPort.id() + "): " + e.getMessage() ); } } } /*try { installProcess.run(); } catch( ExitingException e ) { assert false; }*/ } 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, "Output message 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; } }