#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

from __future__ import print_function
import optparse, sys, traceback
from qpid.messaging import *
from qpid.util import URL
from subprocess import Popen, STDOUT, PIPE
from qpid.log import enable, DEBUG, WARN

parser = optparse.OptionParser(usage="usage: %prog [options] ADDRESS ...",
                               description="handle requests from the supplied address.")
parser.add_option("-b", "--broker", default="localhost",
                  help="connect to specified BROKER (default %default)")
parser.add_option("-r", "--reconnect", action="store_true",
                  help="enable auto reconnect")
parser.add_option("-i", "--reconnect-interval", type="float", default=3,
                  help="interval between reconnect attempts")
parser.add_option("-l", "--reconnect-limit", type="int",
                  help="maximum number of reconnect attempts")
parser.add_option("-v", dest="verbose", action="store_true",
                  help="enable logging")

opts, args = parser.parse_args()

if opts.verbose:
  enable("qpid", DEBUG)
else:
  enable("qpid", WARN)

if args:
  addr = args.pop(0)
else:
  parser.error("address is required")

conn = Connection(opts.broker,
                  reconnect=opts.reconnect,
                  reconnect_interval=opts.reconnect_interval,
                  reconnect_limit=opts.reconnect_limit)
def dispatch(msg):
  msg_type = msg.properties.get("type")
  if msg_type == "shell":
    proc = Popen(msg.content, shell=True, stderr=STDOUT, stdin=PIPE, stdout=PIPE)
    output, _ = proc.communicate()
    result = Message(output)
    result.properties["exit"] = proc.returncode
  elif msg_type == "eval":
    try:
      content = eval(msg.content)
    except:
      content = traceback.format_exc()
    result = Message(content)
  else:
    result = Message("unrecognized message type: %s" % msg_type)
  return result

try:
  conn.open()
  ssn = conn.session()
  rcv = ssn.receiver(addr)

  while True:
    msg = rcv.fetch()
    response = dispatch(msg)
    snd = None
    try:
      snd = ssn.sender(msg.reply_to)
      snd.send(response)
    except SendError as e:
      print(e)
    if snd is not None:
      snd.close()
    ssn.acknowledge()
except ReceiverError as e:
  print(e)
except KeyboardInterrupt:
  pass

conn.close()
