class WinRM::WSMV::ReceiveResponseReader
Class for reading wsmv Receive_Response messages
Attributes
Public Class Methods
Creates a new ReceiveResponseReader
@param transport [HttpTransport] The WinRM
SOAP
transport @param logger [Logger] The logger to log diagnostic messages to
# File lib/winrm/wsmv/receive_response_reader.rb, line 30 def initialize(transport, logger) @transport = transport @logger = logger @output_decoder = CommandOutputDecoder.new end
Public Instance Methods
Reads streams and returns decoded output @param wsmv_message [WinRM::WSMV::Base] A wsmv message to send to endpoint @yieldparam [string] standard out response text @yieldparam [string] standard error response text @yieldreturn [WinRM::Output] The command output
# File lib/winrm/wsmv/receive_response_reader.rb, line 43 def read_output(wsmv_message) with_output do |output| read_response(wsmv_message, true) do |stream, doc| handled_out = handle_stream(stream, output, doc) yield handled_out if handled_out && block_given? end end end
Reads streams sent in one or more receive response messages @param wsmv_message [WinRM::WSMV::Base] A wsmv message to send to endpoint @param wait_for_done_state whether to poll for a CommandState of Done @yieldparam [Hash] Hash representation of stream with type and text @yieldparam [REXML::Document] Complete SOAP
envelope returned to wsmv_message
# File lib/winrm/wsmv/receive_response_reader.rb, line 57 def read_response(wsmv_message, wait_for_done_state = false) resp_doc = nil until command_done?(resp_doc, wait_for_done_state) logger.debug('[WinRM] Waiting for output...') resp_doc = send_get_output_message(wsmv_message.build) logger.debug('[WinRM] Processing output') read_streams(resp_doc) do |stream| yield stream, resp_doc end end end
Protected Instance Methods
# File lib/winrm/wsmv/receive_response_reader.rb, line 71 def with_output output = WinRM::Output.new yield output output.exitcode ||= 0 output end
Private Instance Methods
# File lib/winrm/wsmv/receive_response_reader.rb, line 106 def command_done?(resp_doc, wait_for_done_state) return false unless resp_doc return true unless wait_for_done_state REXML::XPath.match( resp_doc, "//*[@State='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/" \ "CommandState/Done']" ).any? end
# File lib/winrm/wsmv/receive_response_reader.rb, line 80 def handle_stream(stream, output, resp_doc) decoded_text = @output_decoder.decode(stream[:text]) return unless decoded_text out = { stream[:type] => decoded_text } output << out if (code = REXML::XPath.first(resp_doc, "//*[local-name() = 'ExitCode']")) output.exitcode = code.text.to_i end [out[:stdout], out[:stderr]] end
# File lib/winrm/wsmv/receive_response_reader.rb, line 117 def read_streams(response_document) body_path = "/*[local-name() = 'Envelope']/*[local-name() = 'Body']" path = "#{body_path}/*[local-name() = 'ReceiveResponse']/*[local-name() = 'Stream']" REXML::XPath.match(response_document, path).each do |stream| next if stream.text.nil? || stream.text.empty? yield type: stream.attributes['Name'].to_sym, text: stream.text end end
# File lib/winrm/wsmv/receive_response_reader.rb, line 92 def send_get_output_message(message) @transport.send_request(message) rescue WinRMWSManFault => e # If no output is available before the wsman:OperationTimeout expires, # the server MUST return a WSManFault with the Code attribute equal to # 2150858793. When the client receives this fault, it SHOULD issue # another Receive request. # http://msdn.microsoft.com/en-us/library/cc251676.aspx raise unless e.fault_code == '2150858793' logger.debug('[WinRM] retrying receive request after timeout') retry end