import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;

/**
 * Program Name
 *  PutQuit
 *
 * Description
 *  This java class will:
 *  - connect to a remote queue manager
 *  - create a message with feedback of Quit
 *  - Issue an MQPUT1 
 *  - disconnect from queue manager
 *
 * Sample Command Line Parameters
 *  -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q REQUEST.Q -u userId -x password
 *
 * @author Roger Lacroix, Capitalware Inc.
 */
public class PutQuit
{
   private static final SimpleDateFormat  lOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");

   private Hashtable<String, String>   params = null;
   private Hashtable<String, Object>   mqht;
   private String                      qMgrName;
   private String                      outputQName;
   private static PrintStream          ps = null;
   private static boolean              debugMe = false;

   /**
    * The constructor
    * @param args
    * @throws IllegalArgumentException
    * @throws ClassNotFoundException
    */
   public PutQuit(String[] args)  throws IllegalArgumentException, ClassNotFoundException
   {
      super();
//      writeLogToFile();  // have logging info go to a file rather than console.
      
      if (debugMe) PutQuit.logger("");
      
      PutQuit.logger("Starting");
      
      initParms(args);

      begin();
   }

   /**
    * Extract the command-line parameters and initialize the MQ HashTable.
    * @param args
    * @throws IllegalArgumentException
    */
   private void initParms(String[] args) throws IllegalArgumentException
   {
      if (debugMe) PutQuit.logger("");

      int port = 1414;
      params = new Hashtable<String, String>(10);
      if (args.length > 0 && (args.length % 2) == 0)
      {
         for (int i = 0; i < args.length; i += 2)
         {
            params.put(args[i], args[i + 1]);
         }
      }
      else
      {
         throw new IllegalArgumentException();
      }

      if (allParamsPresent())
      {
         qMgrName = (String) params.get("-m");
         outputQName = (String) params.get("-q");
         
         try
         {
            port = Integer.parseInt((String) params.get("-p"));
         }
         catch (NumberFormatException e)
         {
            port = 1414;
         }

         mqht = new Hashtable<String, Object>();
         
         mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
         mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
         mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
         mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
         mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));

         // I don't want to see MQ exceptions at the console.
         MQException.log = null;
      }
      else
      {
         throw new IllegalArgumentException();
      }
   }

   /**
    * Make sure the required parameters are present.
    * @return true/false
    */
   private boolean allParamsPresent()
   {
      if (debugMe) PutQuit.logger("");

      boolean b = params.containsKey("-h") && params.containsKey("-p") &&
                  params.containsKey("-c") && params.containsKey("-m") &&
                  params.containsKey("-q") && 
                  params.containsKey("-u") && params.containsKey("-x");
      if (b)
      {
         try
         {
            Integer.parseInt((String) params.get("-p"));
         }
         catch (NumberFormatException e)
         {
            b = false;
         }
      }

      return b;
   }

   /**
    * Connect, issue MPUT1 & disconnect.
    */
   private void begin()
   {
      if (debugMe) PutQuit.logger("");

      MQQueueManager qMgr = null;

      try
      {
         qMgr = new MQQueueManager(qMgrName, mqht);
         PutQuit.logger("successfully connected to "+ qMgrName);

         MQMessage quitMsg = new MQMessage();
         quitMsg.messageId = CMQC.MQMI_NONE;
         quitMsg.correlationId = CMQC.MQCI_NONE;
         quitMsg.feedback = CMQC.MQFB_QUIT;
         quitMsg.format = CMQC.MQFMT_STRING;
         quitMsg.messageType = CMQC.MQMT_DATAGRAM;
         quitMsg.writeString("QUIT");
         
         // Send the message
         qMgr.put(outputQName, qMgrName, quitMsg);
         PutQuit.logger("Sent QUIT message.");
      }
      catch (MQException e)
      {
         PutQuit.logger("cc=" +e.completionCode + " : rc=" + e.reasonCode);
      }
      catch (IOException e)
      {
         PutQuit.logger(e.getLocalizedMessage());
      }
      finally
      {
         if ( qMgr != null)
         {
            try
            {
               qMgr.disconnect();
               PutQuit.logger("disconnected from "+ qMgrName);
            }
            catch (MQException e)
            {
               PutQuit.logger("disconnect cc=" +e.completionCode + " : rc=" + e.reasonCode);
            }
         }
      }
   }

   /**
    * Code to setup to have logging information go to a file rather than console.
    */
   private void writeLogToFile()
   {
      if (debugMe) PutQuit.logger("");

      try
      {
         String logFile = "PutQuit.log";

         if ((new File(logFile)).length() > 1048576)                     // Larger than 1MB
            ps = new PrintStream(new FileOutputStream(logFile, false));  // create new
         else
            ps = new PrintStream(new FileOutputStream(logFile, true));   // append
      }
      catch(Exception e)
      {
         PutQuit.logger(e.getLocalizedMessage());
      }

      if (ps != null)
      {
         System.setOut(ps);
         System.setErr(ps);
      }
   }

   /**
    * A simple logger method
    * @param data
    */
   public static void logger(String data)
   {
      String className = Thread.currentThread().getStackTrace()[2].getClassName();

      // Remove the package info.
      if ( (className != null) && (className.lastIndexOf('.') != -1) )
         className = className.substring(className.lastIndexOf('.')+1);

      System.out.println(lOGGER_TIMESTAMP.format(new Date())+" "+className+": "+Thread.currentThread().getStackTrace()[2].getMethodName()+": "+data);
   }

   /**
    * main line
    * @param args
    */
   public static void main(String[] args)
   {
      if (System.getProperty("PutQuit_DEBUG") != null)
         debugMe = true;

      try
      {
         new PutQuit(args);
      }
      catch (ClassNotFoundException e)
      {
         PutQuit.logger(e.getLocalizedMessage());
      }
      catch (IllegalArgumentException e)
      {
         System.err.println("Usage: java PutQuit -m QueueManagerName -h host -p port -c channel -q RequestQueueName -u userId -x password");
      }
      
      PutQuit.logger("Ending");
   }
}
