import java.util.Date;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.*;
import java.text.*;

class JMSSend {

    /**
     * Defines the JNDI context factory.
     */
    public final static String DEFAULT_JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

    /**
     * Defines the JMS connection factory for the queue.
     */
    public final static String DEFAULT_JMS_CONNECTION_FACTORY = "weblogic.jws.jms.QueueConnectionFactory";

    /**
     * Defines the queue.
     */
    public final static String DEFAULT_QUEUE = "CCInboundQueue";
    public final static String DEFAULT_OUTQUEUE = "CCOutboundQueue";

    /**
     * Default URL
     */
    public static String URL="t3://localhost:7001";
    private static final int DEFAULT_TIMEOUT_SECS = 180;
    private String _convidBase;

    int seqnum;
    private final static String COORPROPNAME="ASYNC_BIN_SEL";

    private java.util.Date txnDate;
    private static SimpleDateFormat nodelimeterFormat = new SimpleDateFormat("yyyyMMddhhmmss");
    private final static String creditcardNumbers[] =
    {
        "1212121212121212",
	"1312121212121212",
        "1412121212121212",
        "1512121212121212"
    };

    private final static String creditcardInfo[] =
    {
        ",1234 First Street,,San Jose,CA,94567,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,",
        ",2341 Second Street,,Santa Barbara,CA,94567,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,",
	",3412 Third Street,,San Raffel,CA,94567,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,",
	",4123 Fourth Street,,San Ramon,CA,94567,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,"
    };

    private QueueConnectionFactory qConnectionFactory;
    private QueueConnection qConnection;

    //JMS Send Information
    private	QueueSender qSender;
    private	QueueSession qSendSession;
    private	Queue sendQ;

    //JMS Receive Information
    private QueueReceiver qreceiver;
    private QueueSession qreceivesession;
    private Queue replyQ;


    private static InitialContext getInitialContext() throws NamingException {

        Hashtable env = new Hashtable();
        env.put( Context.INITIAL_CONTEXT_FACTORY, DEFAULT_JNDI_FACTORY );
        env.put( Context.PROVIDER_URL, URL);
        return new InitialContext( env );
    }

    public void init(Context ctx) throws Exception
    {
	System.out.println( "Looking up connection factory" );
	qConnectionFactory =( QueueConnectionFactory ) ctx.lookup( DEFAULT_JMS_CONNECTION_FACTORY );

	System.out.println( "Creating connection & session" );
	qConnection = qConnectionFactory.createQueueConnection();
	qSendSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

	System.out.println( "Looking up queue object" );
	sendQ = (Queue) ctx.lookup(DEFAULT_QUEUE);

	System.out.println( "Creating sender" );
	qSender = qSendSession.createSender(sendQ);

	qreceivesession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	replyQ = (Queue) ctx.lookup(DEFAULT_OUTQUEUE);

	System.out.println( "Starting connection" );
	qConnection.start();
    }

    public void close() throws Exception{
	qSender.close();
	qSendSession.close();
	qreceivesession.close();
	qConnection.close();
    }

    private String getConvId() {
        if (_convidBase == null) {
            _convidBase= Long.toString(System.currentTimeMillis());
        }
        return _convidBase + seqnum++;
    }

    /**
     * Does a blocking wait on RECEIVE_QUEUE
     */
    public void sendReceive(String msgTxt, int len) throws Exception  {

	int i=0, j=0, k=0;

	String msgs[] = new String[4*10000];
	String reqAmt = "1";
	if (!msgTxt.equals("done") )
	    {
		for (i=0 ; i<len; i++)
		    {
			for (j=0; j<4; j++) {
			    msgs[k]=creditcardNumbers[j]+","+k+","+reqAmt+creditcardInfo[j]+nodelimeterFormat.format(new Date());
			    k++;
			}
		    }
		System.out.println("sending "+len+" messages for 4 credit cards from "+len*4+" different stores.");
	    }

	System.out.println( "Creating text message" );
	TextMessage message = qSendSession.createTextMessage();
	String msgid=null;

	//	    --- Processing starts here ---------------------------------------------------
	if (!msgTxt.equals("done"))
	    {
		for( i = 0; i< k; i++ )
		    {
			msgid = getConvId();
			System.out.println("Message id while sending :  "+msgid);

			if (i%100 == 0 && i!=0) {
			    System.out.println("Sent "+i+" messages.");
			}
			message.setStringProperty( COORPROPNAME, msgid );
			message.setText( msgs[i] );
			qSender.send(message);
			System.out.println( "==> Successfully sent" );

			String _selector = COORPROPNAME + " = '" + msgid + "'";
			System.out.println("Receiving reply messages");
			qreceiver = qreceivesession.createReceiver(replyQ, _selector);

			TextMessage txtMsg=null;
			boolean done = false;
			while (!done) {
			    //Block for message or 3 mins.
			    txtMsg = (TextMessage)qreceiver.receive(DEFAULT_TIMEOUT_SECS * 1000);

			    if (txtMsg == null)
				{
				    throw new Exception("Test timed out. Did not receive reply from JPD! Received only ");
				}

			    String gotid = txtMsg.getStringProperty( COORPROPNAME );
			    if (gotid == null) {
				System.out.println("Got message w/o a cooralation property");
			    }
			    else {
				if (gotid.compareTo(msgid) != 0) {
				    System.out.println( "Uncorrelated id: " + gotid);
				}
				else {
				    System.out.println("Message matches, success");
				    done = true;
				}
			    }
			}
			qreceiver.close();
		    }
	    }
	else
	    {
		message.setText(msgTxt);
		qSender.send(message);
		System.out.println("Sent \'"+msgTxt+"\' message.");
	    }
    }

    public static void main(String[] args)
    {
	Context ctx = null;
	JMSSend jmssendinst=null;

        int messagesReceived = 0;
	String msgTxt="Test message";
	int len =0;

	if (args.length <=0) {
	    System.out.println("Please enter between 1 and 10,000 messages or say JMSSend done to complete the test.");
	    System.exit(1);
	}
	if (args[0].equalsIgnoreCase("done"))
	    msgTxt="done";
	else
	    len = Integer.parseInt(args[0]);
	if (args.length >1)
	    URL=args[1];
	try {
	    jmssendinst = new JMSSend();
	    System.out.println( "Creating initial context" );
	    ctx = getInitialContext();
	    jmssendinst.init(ctx);
	    jmssendinst.sendReceive(msgTxt,len);

	} catch( Exception ex ) {
	    ex.printStackTrace();
	} finally {
	    try {
		jmssendinst.close();
	    }catch(Exception e){
		System.out.println("JMSException : "+e.getMessage());
	    }
	}
    }
}
