/*
 * Created on Jun 25, 2003
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package com.marco.config;
import javax.management.*;
import java.util.Date;
import java.util.Vector;
import java.util.Set;
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.*;
import javax.jms.*;
import javax.management.timer.*;
import java.lang.reflect.*;
/**
 * @author mistroni
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class MyTimerTrial extends org.jboss.system.ServiceMBeanSupport implements DynamicMBean
							 {
									   
	private MBeanServer server;
	private ObjectName timer;
	private int timeout;
	private int repetitions;
	private Topic emailtopic;
	private Topic smstopic;
	private TopicConnection topicConnection;
	private TopicPublisher emailPublisher;
	private TopicPublisher smsPublisher;
	private TopicSession session;
	protected MBeanInfo mbeanInfo = null;
	protected Hashtable attributes = new Hashtable();
	protected Hashtable notifications = new Hashtable();
	protected Hashtable constructors = new Hashtable();
	protected Hashtable operations = new Hashtable();
	protected String description = "Description of MBean";

	
	public MyTimerTrial() {
		//super();
		
		
		System.err.println("MytimerTrial initialized!!!");
	}
	
	// Here we add informations to be used in MBeanInfo.
	// we have to add all operations, attributes and notifications
	// that our MBeab will have.
	private void addMBeanInfoData() {
		System.err.println("Adding mbeaninfo data..");
		String[] addNotificationparamNames = {
					  "Notification Type",
					  "Notification Message",
					  "Destination",
					  "Content",
					  "Sender",
					  "Timeout",
                      "Repetitions"
        			};

		String[] addNotificationparamTypes = {
					  "java.lang.String",
		  			  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String",
                	  "java.lang.String"
         			};

		String[] addNotificationparamDesc = {
					  "Notification Type",
					  "Notification Message",
					  "Destination of the notification",
					  "Content of message",
					  "Email address of the sender",
					  "Interval at which notifications will be sent",
                	  "Number of times that the repetition will be sent"
                	};
		// Adding operation addNotification
		addMBeanOperation("addNotification", addNotificationparamTypes,
		 				  addNotificationparamNames, addNotificationparamDesc,
						  "Adds a Notification", "void",
						  MBeanOperationInfo.ACTION);
 
 		String[] addNotificationBombparamNames = {
					  "Notification Type",
	  				  "Notification Message",
	  				  "Destination",
					  "Content",
					  "Sender",
                	  "Timeout"
               	      };

		String[] addNotificationBombparamTypes = {
					  "java.lang.String",
		   			  "java.lang.String",
		   			  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String",
                	  "java.lang.String"
                	};

		String[] addNotificationBombparamDesc = {
					  "Notification Type",
		 			  "Notification Message",
		 			  "Destination of the notification",
					  "Content of message",
                	  "Email of the sender",
					  "Interval at which notifications will be sent"
                	};

		// Adding operation addNotificationBomb
		addMBeanOperation("addNotificationBomb", addNotificationBombparamTypes,
		 				  addNotificationBombparamNames, addNotificationBombparamDesc,
						  "Adds a Notification which will be sent forever", "void",
						  MBeanOperationInfo.ACTION);
 
		String[] addSMSNotificationparamNames = {
					  "Notification Message",
					  "Destination",
					  "Timeout",
					  "Repetitions"
					};

		String[] addSMSNotificationparamTypes = {
					  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String",
					  "java.lang.String"
					  
					};

		String[] addSMSNotificationparamDesc = {
					  "Notification Message",
					  "Destination of the notification",
					  "Interval at which notifications will be sent",
					  "Number of times that the repetition will be sent"
					};
		// Adding operation addNotification
		addMBeanOperation("addSMSNotification", addSMSNotificationparamTypes,
						  addSMSNotificationparamNames, addSMSNotificationparamDesc,
						  "Adds a SMSNotification", "void",
						  MBeanOperationInfo.ACTION);

 		
 		String[] removeNotificationparamNames = {
 							  "Notification Type"
 					};

		String[] removeNotificationparamTypes = {
							  "java.lang.String"
					};

		String[] removeNotificationparamDesc = {
							  "The typen of Notification to be removed"
					};

	    // Adding operation removeNotification
	    addMBeanOperation("removeNotification", removeNotificationparamTypes,
								 removeNotificationparamNames, removeNotificationparamDesc,
								 "Removes a Notification", "void",
								 MBeanOperationInfo.ACTION);
   	
   		String[] stopParamNames = {};
   		String[] stopParamTypes = {};
   		String[] stopParamDesc = {};
   		addMBeanOperation("removeAllNotifications", stopParamTypes, stopParamNames,
   						  stopParamDesc, "removes all notifications","void",
   						  MBeanOperationInfo.ACTION); 
   	
		addMBeanOperation("start", stopParamTypes, stopParamNames,
						  stopParamDesc, "start the mbean","void",
						  MBeanOperationInfo.ACTION );
						  
		addMBeanOperation("stop", stopParamTypes, stopParamNames,
								  stopParamDesc, "stop the mbean","void",
								  MBeanOperationInfo.ACTION );
								  
		addMBeanOperation("init", stopParamTypes, stopParamNames,
								  stopParamDesc, "initializes the mbean","void",
								  MBeanOperationInfo.ACTION );
								  
				  
	
	}
	
		
	// Code below is generated automatically by MBeanGenerator.
	// You may need to modify it according to your needs :-)

	public Object invoke(String method, Object args[],
				         String types[]) throws MBeanException, ReflectionException {
		try {
			Class c = this.getClass();
			Class sig[] = null;
			if(types != null) {
				sig = new Class[types.length];
				for(int i=0; i < types.length; i++) {
					sig[i] = Class.forName(types[i]);
				}
			}
			Method m = c.getDeclaredMethod(method, sig);
			Object returnObject = (Object)m.invoke(this, args);
			return returnObject;
		} catch(Exception e) {
			System.err.println("Error in DynamicMBeanSupport.invoke():\n" + e.toString());
			return null;
		}
    }				         	
	
	
	
	public Object getAttribute(String name) throws MBeanException, ReflectionException {
		try {
			Class c = this.getClass();
			Method m = c.getDeclaredMethod("get" + name, null);
			return m.invoke((Object)this, null);
		} catch(Exception e) {
			System.err.println("Exception in DynamicMBeanSupport.getAttribute()\n" + e.toString());
			return null;
		}
	}	
	
	public void setAttribute(Attribute attribute) throws MBeanException, AttributeNotFoundException,
	   												     ReflectionException, InvalidAttributeValueException {
		String fname = attribute.getName();
		Object fvalue = attribute.getValue();
		try {
			Class c = this.getClass();
			String type = getType(fname, false, true);
			if(type == null) 
				throw new AttributeNotFoundException(fname);
		
			Class[] types =  {Class.forName(type)};
			Method m = c.getDeclaredMethod("set" + fname, types);
			
			Object[] args = {fvalue};
			m.invoke((Object)this, args);														  	
		} catch(AttributeNotFoundException e) {
			System.err.println("Exception in DynamicMBeanSupport.setAttribute()\n" + e.toString());
			throw e;
		} catch(Exception e) {
			System.err.println("Exception2 in DynamicMBeanSupport.setAttribute()\n" + e.toString()); 
			
		}
     }
	
	public AttributeList setAttributes(AttributeList attributes) {
		Attribute[] atts = (Attribute[])attributes.toArray();
		AttributeList list = new AttributeList();
		for(int i=0; i < atts.length; i++) {
			Attribute a = atts[i];
			try {
				this.setAttribute(a);
			} catch(Exception e) {
				System.err.println("Exception in DynamicMBeanSupport.setAttributes()\n" + e.toString());
			}
		} // end for
		return attributes;
	}
	
	public AttributeList getAttributes(String[] names) {
		AttributeList list = new AttributeList();
		for(int i=0; i < names.length; i++) {
			try {
				list.add(new Attribute(names[i],
				this.getAttribute(names[i])));
			} catch(Exception e) {
				System.err.println("Exception in DynamicMBeanSupport.getAttributes()\n" + e.toString());
			}
		}
		return list;
	}
	
	public MBeanInfo getMBeanInfo() {
		try {
			 addMBeanInfoData();
			 buildDynamicMBeanInfo();
		} catch(Exception e ) {
			System.err.println("Exception in DynamicMBeanSupport.getMBeanInfo()\n" + e.toString());
		}
			return mbeanInfo;
	}
	
	protected void addMBeanOperation(String name, String[] paramTypes, 
						             String[] paramNames, String[] paramDescs, 
						             String desc, String rtype, int type) {
		MBeanParameterInfo[] params = null;
		if(paramTypes != null) {
			params = new MBeanParameterInfo[paramTypes.length];
			for(int i=0; i < paramTypes.length; i++) {
				params[i] = new MBeanParameterInfo(paramNames[i], paramTypes[i], paramDescs[i]);
			}
		}
		operations.put(name, new MBeanOperationInfo(name, desc, params, rtype, type));
									 
    }
	
	protected void addMBeanAttribute(String fname, String ftype, 
						             boolean read, boolean write, boolean is,
						             String desc) {
		attributes.put(fname, new MBeanAttributeInfo(fname,ftype, desc, read, write, is));
	}

	protected void addMBeanNotification(String type, String name, String description) {
		notifications.put(name, new MBeanNotificationInfo(new String[] {type}, name, description));
    }
	
	protected void addMBeanConstructor(Constructor c, String desc) {
		this.constructors.put(c, new MBeanConstructorInfo(desc, c));
	}
	
	private void copyInto(Object[] array, Hashtable table) {
		Vector temp = new Vector(table.values());
		temp.copyInto(array);
	}
	
	private String getType(String attName, boolean read, boolean write) {
		boolean allowed = true;
		if(attributes.containsKey(attName)) {
			MBeanAttributeInfo temp = (MBeanAttributeInfo)attributes.get(attName);
			if(read) {
				if(!temp.isReadable())
					allowed = false;
				}
			if(write) {
				if(!temp.isWritable()) 
					allowed = false;
			}
			
			if(!allowed)
				return null;
			else
				return temp.getType();
		} else
			return null;
	}	
	
	private void buildDynamicMBeanInfo() throws Exception {
		MBeanOperationInfo[] ops = new MBeanOperationInfo[operations.size()];
		copyInto(ops, operations);
		
		MBeanAttributeInfo[] atts = new MBeanAttributeInfo[attributes.size()];
		copyInto(atts, attributes);
	
		MBeanConstructorInfo[] cons = new MBeanConstructorInfo[constructors.size()];
		copyInto(cons, constructors);

			MBeanNotificationInfo[] notifs = new MBeanNotificationInfo[notifications.size()];
			copyInto(notifs, notifications);
		
		mbeanInfo = new MBeanInfo(this.getClass().getName(), description, atts,
								  cons, ops,null);
	}
	
	
	   
	/**
		 * @return the name of this MBean
		 */
		public String getName() {
			return "MyTimerTrial";
		}

		/**
		 * Initializes the MBean by getting references
		 * to JMS objects in order to send email..
		 * @throws Exception
		 */
		public void init() throws MalformedObjectNameException,
								  InstanceNotFoundException  {
			try {
				
				System.err.println("******************************Looking up JMS destination.*************.....");
				
				Properties env = new Properties();
				env.put(Context.PROVIDER_URL, "jnp://L1403041:1099");
				env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
				env.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
				InitialContext ctx = new InitialContext(); //(env);
				System.err.println("Looking up ConnectionFactory..");
			
				TopicConnectionFactory tcf = (TopicConnectionFactory)ctx.lookup("ConnectionFactory");
				if(tcf != null)
					System.err.println("Successfully obtained tcf.");
				else
					System.err.println("TCF is null!");
				System.err.println("Looking up Destination..");
				emailtopic = (Topic)ctx.lookup("topic/EMailMsgBean");//topic/myTestTopic");
				smstopic = (Topic)ctx.lookup("topic/SMSMsgBean");
				System.err.println("Creating topicconnection..");
				topicConnection = tcf.createTopicConnection();
				System.err.println("Creating topicsession..");
				session  = topicConnection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
				emailPublisher  =session.createPublisher(emailtopic);
				smsPublisher = session.createPublisher(smstopic);
				
				System.err.println("Finished to initialize JMS objects..");
			} catch(Exception e) {
				System.err.println("Exception in initialization:\n");
				e.printStackTrace();
			}
		}
		
		public void start() throws InstanceNotFoundException,MBeanException, ReflectionException,Exception {
			System.err.println("Starting MyTimerTrial..");
			try {
				System.err.println("In MyTimerTrial.start(). Initializing JMS..");
				init();
			} catch(Exception e) {
				System.err.println("Exception in initialization of MyTimerTrial!\n" + e.toString());;
			}
		}
		
		public void stop() {
			try {
				System.err.println("Stopping MyTimerTrial..");
				topicConnection.close();
			} catch(Exception e) {
				System.err.println("Exception in stopping myTimerTrial..");
			}
		}
		
		public ObjectName preRegister(MBeanServer server, ObjectName name) {
			// We need this only to get a reference
			// to the MBean server..
			this.server = server;
			System.err.println("Initializing TimerMBean....");
			try {
				Set mbeans = server.queryMBeans(new ObjectName("DefaultDomain", 
															   "service",
															   "timer"), null);
				System.err.println("Got successfully timer...");											   
				if(!mbeans.isEmpty()) {
					// Should be the first and only one..
					timer = ((ObjectInstance)mbeans.iterator().next()).getObjectName();
		
					System.err.println("Adding notification listener..");
					server.addNotificationListener(timer,
												   new Listener(),
												   null,
												   null);
				} else {
					System.err.println("** No Timer MBean found!");
				}
			
			} catch(Exception e) {
				System.err.println("Exception in MyTimer.preRegister():\n" + e.toString());
			}
			return name;
	
		}
	
		public void addNotification(String type,
									String message,
									String destination,
									String content,
									String sender,
									String timeout,
									String repetitions) throws InstanceNotFoundException,
															   MBeanException,
															   ReflectionException  {
			long _timeout = Long.parseLong(timeout);
			Hashtable table = new Hashtable();
			table.put("content", content);
			table.put("destination", destination);
			table.put("sender", sender);
			Object timeoutTimer	= server.invoke(timer,
												"addNotification",
												new Object[] {
													type,
													message,
													table,
													new Date(),
													new Long(_timeout*1000L),
													new Long(repetitions)},
												new String[] {
													String.class.getName(),
													String.class.getName(),
													"java.lang.Object",
													"java.util.Date",
													Long.TYPE.getName(),
													Long.TYPE.getName()});
		}							
    
		public void addSMSNotification(
									String message,
									String destination,
									String timeout,
									String repetitions) throws InstanceNotFoundException,
															   MBeanException,
															   ReflectionException  {
			long _timeout = Long.parseLong(timeout);
			Object timeoutTimer	= server.invoke(timer,
												"addNotification",
												new Object[] {
													"SMSNotification",
													message,
													destination,
													new Date(),
													new Long(_timeout*1000L),
													new Long(repetitions)},
												new String[] {
													String.class.getName(),
													String.class.getName(),
													"java.lang.Object",
													"java.util.Date",
													Long.TYPE.getName(),
													Long.TYPE.getName()});
		}
    
    
    
		public void addNotificationBomb(String type,
									String message,
									String destination,
									String content,
									String sender,
									String timeout) throws InstanceNotFoundException,
															   MBeanException,
															   ReflectionException  {
    
			long _timeout = Long.parseLong(timeout);
			Hashtable table = new Hashtable();
			table.put("content", content);
			table.put("destination", destination);
			table.put("sender", sender);
			Object timeoutTimer	= server.invoke(timer,
												"addNotification",
												new Object[] {
													type,
													message,
													table,
													new Date(),
													new Long(_timeout*1000L),
													},
												new String[] {
													String.class.getName(),
													String.class.getName(),
													"java.lang.Object",
													"java.util.Date",
													Long.TYPE.getName()
													});
		}
    							
		public void removeNotification(String type) {
			try {
				// stop timer by removing notifications
				server.invoke(timer, "removeNotifications",
							  new Object[] {type},
							  new String[]  {"java.lang.String"});
			
			} catch(Exception e) {
				System.err.println("Cannot stop scheduler timer");
				e.printStackTrace();
			}
		}
	
		public void removeAllNotifications() {
			try {
				// stop timer by removing notifications
				server.invoke(timer, "removeAllNotifications",
							  new Object[] {},
							  new String[]  {});
			} catch(Exception e) {
				System.err.println("Cannot stop scheduler timer");
				e.printStackTrace();
			}
		
		}

		protected void sendResponse(Hashtable table) {
			try {
				System.err.println("Sending message...");
				//Hashtable table  = new Hashtable();
				//table.put("message", msg);
				//table.put("destination", email);
				Message message = session.createObjectMessage(table);
				emailPublisher.publish(message);
			} catch(Exception e) {
				System.err.println("MyTimer. Got exception in sending JMS message..\n" + e.toString());
			
			}
		}
	
		protected void sendSMS(String message, String destination) {
			try {
				System.err.println("Sending sms..");
				Hashtable table  = new Hashtable();
				table.put("message", message);
				table.put("destination", destination);
				Message _message = session.createObjectMessage(table);
				smsPublisher.publish(_message);
			} catch(Exception e) {
				System.err.println("MyTimer. Got exception in sending JMS sms..\n" + e.toString());
			}
		}
	
		// the NotificationListener class...
		class Listener implements NotificationListener {
			/**
			 * Event handler
			 */
			public void handleNotification(Notification pNotification,
										   Object handBack) {
	        
				//System.err.println(pNotification.getMessage()+ "|handback=" + pNotification.getUserData());							   		
				if(pNotification.getType().equals("SMSNotification")) {
					sendSMS(pNotification.getMessage(), (String)pNotification.getUserData());
				}
			
				Hashtable table = (Hashtable)pNotification.getUserData();
				table.put("message",pNotification.getMessage());
				sendResponse(table);//pNotification.getMessage(), (String)pNotification.getUserData());
			}
		}


	
}
