package examples.xml.jms;

import java.io.*;
import java.util.*;
import javax.jts.*;
import javax.naming.*;
import javax.jms.*;
import org.w3c.dom.*;
import com.sun.xml.tree.XmlDocumentBuilder;
import com.sun.xml.parser.Parser;
import com.sun.xml.parser.Resolver;
import org.xml.sax.InputSource;
import com.sun.xml.tree.ElementNode;
import com.sun.xml.tree.XmlDocument;

/**
 * This example shows how to pass XML data within a JMS message. The 
 * classes in this package make up a simple workflow system. This class 
 * is used to create a message which requires approval from the 
 * <tt>AdminClient</tt>. The message is combined in the form of  
 * XML data with the name of the user who sent the message and the 
 * current status of the message. The XML data is sent as a JMS text 
 * message to a queue where it awaits approval from the <tt>AdminClient</tt>.
 * The <tt>AdminClient</tt> updates attributes of the XML data and returns 
 * it to the queue. The message is then read back in by this class which 
 * parses the XML data using a SAX compliant parser and displays the results 
 * in the console.
 *
 * @author Copyright (c) 2000 by BEA Systems, Inc. All Rights Reserved.
 */
public class Client
  implements MessageListener
{
  public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
  public final static String JMS_FACTORY="javax.jms.QueueConnectionFactory";
  public final static String QUEUE="javax.jms.exampleQueue";
  public final static String PARSER="com.sun.xml.parser.ValidatingParser";

  private QueueConnectionFactory qconFactory;
  private QueueConnection qcon;
  private QueueSession qsession;
  private QueueReceiver qreceiver;
  private QueueSender qsender;
  private Queue queue;
  private String username;
  private TextMessage msg;

  /**
   * Called when a message is received from the JMS message queue. (MessageListener interface)
   */
  public void onMessage(Message message)
  {
    try {
      // obtain a DOM parser and associate the resolver and document builder
      Parser parser = new com.sun.xml.parser.Parser();

      // use custom entity resolver to locate the DTD when parsing
      ResourceEntityResolver rer = new ResourceEntityResolver();
      rer.addEntityResource(
        "weblogic-examples-xml-jms-dtd", 
        "workflow.dtd", 
        getClass());
      parser.setEntityResolver(rer);

      XmlDocumentBuilder builder = new XmlDocumentBuilder();
      builder.setDisableNamespaces(true);
      builder.setParser(parser);
      
      // get the message and parse
      String msgText = ((TextMessage) message).getText();
      parser.parse(new InputSource(new StringReader(msgText)));

      // get document data and display results to console
      Document doc =  builder.getDocument();
      Element root = doc.getDocumentElement();
      System.out.println("\nYou have a message in you inbox!");
      System.out.println("From: "+ root.getAttribute("sender"));
      System.out.println("Message: "+ root.getAttribute("message"));
      System.out.println("Status of message: "+ root.getAttribute("status"));
      System.out.print("\nEnter another message(\"quit\" to quit): ");
    } catch (Exception e) {
      e.printStackTrace();
    } 
  }

  /**
   * Create all the necessary objects for sending and receiving
   * messages from a JMS queue.
   */
  public void init(Context ctx, String queueName, String name)
       throws NamingException, JMSException
  {
    username = name;
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
   try {
      queue = (Queue) ctx.lookup(queueName);
    } catch (NamingException ne) {
      queue = qsession.createQueue(queueName);
      ctx.bind(queueName, queue);
    }
    String selector = "messageTo = '" + username +"'";
    qreceiver = qsession.createReceiver(queue, selector);
    qreceiver.setMessageListener(this);
    qsender = qsession.createSender(queue);
    msg = qsession.createTextMessage();
    qcon.start();
  }

  /**
   * Close JMS objects.
   */
  public void close()
       throws JMSException
  {
    qreceiver.close();
    qsender.close();
    qsession.close();
    qcon.close();
  }


  /**
   * Runs this example from the command line. 
   */
  public static void main(String[] args)
       throws Exception 
  {
    if (args.length != 2) {
      System.out.println("Usage: java examples.jms.queue.QueueReceive WebLogicURL username");
      return;
    }

    InitialContext ic = getInitialContext(args[0]);
    Client client = new Client();
    client.init(ic, QUEUE, args[1]);
    
    // get message from user
    System.out.print("Enter message (\"quit\" to quit): ");
    BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));
    String line=null;
    boolean quitNow = false;
      do {
        line = msgStream.readLine();
        if (line != null && line.trim().length() != 0) {
          quitNow = line.equalsIgnoreCase("quit");

          // send message to JMS queue
          client.send(line, "pending approval", "admin");
          System.out.println("Your message has been sent to 'admin' and is pending approval.\n");
        }
      } while (! quitNow);
    client.close();
  }

  // gets the initial context to the server
  private static InitialContext getInitialContext(String url)
       throws NamingException
  {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
  }

  /**
   * Send a message in the form of XML data to a JMS queue.
   */
  public void send(String message, String status, String sendTo)
       throws JMSException
  {
    // create a new XML document
    XmlDocument xmlDoc = new XmlDocument();

    // set the document type declaration
    xmlDoc.setDoctype(
      "weblogic-examples-xml-jms-dtd", 
      "http://www.wegblogic.com/docs51/examples/xml/jms/workflow.dtd", 
      "");

    // assign elements and attributes
    Element root = xmlDoc.createElement("workflow");
    root.setAttribute("message", message);
    root.setAttribute("sender", username);
    root.setAttribute("status", status);
    xmlDoc.appendChild(root);
    
    // write document to a String and send as a JMS text message
    StringWriter sw = new StringWriter();
    try {
      xmlDoc.write(sw);
      msg.setText(sw.toString());
      msg.setStringProperty("messageTo", sendTo);
      qsender.send(msg);
    } catch (Exception e) {
      e.printStackTrace();
    } 

  }

}




