All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.messaging.jmq.jmsclient.notification.EventHandler Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2000, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.messaging.jmq.jmsclient.notification;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import jakarta.jms.JMSException;
import jakarta.jms.ExceptionListener;

import com.sun.messaging.Destination;
import com.sun.messaging.jmq.util.DestType;
import com.sun.messaging.jmq.jmsclient.ConnectionImpl;
import com.sun.messaging.jmq.jmsclient.ProtocolHandler;
import com.sun.messaging.jmq.jmsclient.SequentialQueue;
import com.sun.messaging.jmq.jmsclient.resources.ClientResources;

import com.sun.messaging.jmq.jmsclient.Debug;
import com.sun.messaging.jms.notification.*;

import com.sun.messaging.ConnectionConfiguration;

/**
 * MQ Client Runtime event handler.
 *
 * The event handler receives event from the client runtime and notifies the connectiion's event listener.
 * 

*/ public class EventHandler implements Runnable { /** * consumer info types (protocol) for consumer event */ private static final int CONSUMER_NOT_READY = 0; private static final int CONSUMER_READY = 1; private ConnectionImpl connection = null; private Thread handlerThread = null; protected static final String iMQEventHandler = "iMQEventHandler-"; private SequentialQueue eventQueue = null; private boolean isClosed = false; private final HashMap consumerEventListeners = new HashMap<>(); /** * This flag is used to prevent duplicate delivery of ConnectionClosedEvent. This is set to true after each delivery for * the closed event. It is set to false after reconnected. */ private boolean closedEventdelivered = false; private ExceptionListener exlistener = null; public static final long WAIT_TIMEOUT = 2 * 60 * 1000; // 2 minutes. private boolean debug = Debug.debug; private static boolean debugEvent = Boolean.getBoolean("imq.debug.notification"); public EventHandler(ConnectionImpl conn) { this.connection = conn; init(); } private void init() { eventQueue = new SequentialQueue(2); } public void addConsumerEventListener(Destination dest, EventListener listener) throws JMSException { if (isClosed) { throw new JMSException("Event handler is closed"); } synchronized (consumerEventListeners) { consumerEventListeners.put(dest, listener); } } public void removeConsumerEventListener(com.sun.messaging.Destination dest) throws JMSException { synchronized (consumerEventListeners) { if (consumerEventListeners.get(dest) == null) { throw new JMSException("XXXI18N -Consumer event listener for destination " + dest + " not found"); } consumerEventListeners.remove(dest); } } private synchronized void onEvent(Event event) { if (debugEvent) { Debug.getPrintStream().println(new Date() + "-- event triggerred, code = " + event.getEventCode() + ", msg = " + event.getEventMessage()); } if (isClosed) { return; } eventQueue.enqueue(event); if (handlerThread == null) { createHandlerThread(); } notifyAll(); } public synchronized void close() { isClosed = true; notifyAll(); synchronized (consumerEventListeners) { consumerEventListeners.clear(); } } private void createHandlerThread() { synchronized (this) { if (handlerThread == null) { handlerThread = new Thread(this); if (connection.hasDaemonThreads()) { handlerThread.setDaemon(true); } handlerThread.setName(iMQEventHandler + connection.getLocalID()); handlerThread.start(); } } } @Override public void run() { boolean timeoutExit = false; boolean keepRunning = true; while (keepRunning) { timeoutExit = false; synchronized (this) { if (shouldWait()) { try { wait(WAIT_TIMEOUT); } catch (InterruptedException inte) { } } } if (isClosed) { /** * when close() is called, we simply exit the handler. */ return; } else if (eventQueue.isEmpty()) { // timeout occurred. timeoutExit = true; } else { /** * get the event from the queue. */ Event event = (Event) eventQueue.dequeue(); if (event instanceof ConsumerEvent) { deliverConsumerEvent((ConsumerEvent) event); } else if (event instanceof ConnectionExitEvent) { deliverException(event); } else { /** * regular connection event. */ deliverConnectionEvent(event); } } /** * check if we need to continue. */ keepRunning = shouldContinue(timeoutExit); } } private void deliverException(Event event) { try { if (exlistener != null && isClosed == false) { ConnectionExitEvent exitEvent = (ConnectionExitEvent) event; JMSException jmse = exitEvent.getJMSException(); exlistener.onException(jmse); if (debugEvent) { Debug.getPrintStream().println(new Date() + " Exception is delivered to the listener: " + jmse); } } } catch (Exception e) { e.printStackTrace(); } finally { isClosed = true; } } private boolean shouldWait() { return eventQueue.isEmpty() && (connection.hasEventListener() || !consumerEventListeners.isEmpty()) && (!isClosed); } private synchronized boolean shouldContinue(boolean timeoutExit) { boolean keepRunning = true; // exit if closed or timeout. if (isClosed || (timeoutExit && eventQueue.isEmpty())) { this.handlerThread = null; keepRunning = false; } return keepRunning; } private void deliverConnectionEvent(Event event) { EventListener listener = connection.getEventListener(); try { if (shouldDeliver(listener, event)) { listener.onEvent(event); if (debugEvent) { Debug.getPrintStream().println(new Date() + "*** Delivered event, code = " + event.getEventCode() + ", msg = " + event.getEventMessage()); } } } catch (Throwable t) { t.printStackTrace(); } finally { postEventProcess(event); } } private void deliverConsumerEvent(ConsumerEvent event) { com.sun.messaging.Destination dest = event.getDestination(); EventListener listener = null; synchronized (consumerEventListeners) { listener = consumerEventListeners.get(dest); } try { if (shouldDeliver(listener, event)) { listener.onEvent(event); if (debugEvent) { Debug.getPrintStream().println(new Date() + "*** Delivered event, code = " + event.getEventCode() + ", msg = " + event.getEventMessage()); } } } catch (Throwable t) { t.printStackTrace(); } finally { postEventProcess(event); } } private boolean shouldDeliver(EventListener listener, Event event) { boolean canDeliver = true; if (listener == null || isClosed) { canDeliver = false; } else { if (event instanceof ConnectionClosedEvent && closedEventdelivered) { canDeliver = false; } } return canDeliver; } /** * Perform action based on event type and connection state. */ private void postEventProcess(Event event) { // String eid = event.getEventCode(); if (event instanceof ConnectionReconnectedEvent) { // wake up waiting threads on reconnecting connection.setReconnecting(false); // reset flag closedEventdelivered = false; startConnection(); } else if (event instanceof ConnectionClosedEvent) { // set delivered flag closedEventdelivered = true; } } private void startConnection() { try { // if the connection is not in stop mode, restart the connection if (connection.getIsStopped() == false) { connection.getProtocolHandler().start(); } } catch (Exception e) { if (this.debug) { e.printStackTrace(Debug.getPrintStream()); } } } public void triggerConnectionClosedEvent(String evCode, JMSException jmse) { if (connection.getEventListener() == null) { return; } String evMessage = ClientResources.getResources().getKString(evCode, connection.getLastContactedBrokerAddress()); if (evCode.equals(ClientResources.E_CONNECTION_CLOSED_NON_RESPONSIVE)) { evMessage = evMessage + ", " + ConnectionConfiguration.imqPingAckTimeout + ": " + connection.getPingAckTimeout(); } ConnectionClosedEvent event = new ConnectionClosedEvent(connection, evCode, evMessage, jmse); this.onEvent(event); } public void triggerConnectionClosingEvent(String evCode, long timePeriod) { if (connection.getEventListener() == null) { return; } String millisecs = String.valueOf(timePeriod), secs = String.valueOf(timePeriod / 1000); Object params[] = new Object[3]; params[0] = secs; params[1] = millisecs; params[2] = connection.getLastContactedBrokerAddress(); String evMessage = ClientResources.getResources().getKString(evCode, params); ConnectionClosingEvent event = new ConnectionClosingEvent(connection, evCode, evMessage, timePeriod); this.onEvent(event); } public void triggerConnectionReconnectFailedEvent(JMSException jmse, String brokerAddr) { if (connection.getEventListener() == null) { return; } String evCode = ConnectionReconnectFailedEvent.CONNECTION_RECONNECT_FAILED; String evMessage = ClientResources.getResources().getKString(evCode, brokerAddr); ConnectionReconnectFailedEvent event = new ConnectionReconnectFailedEvent(connection, evCode, evMessage, jmse); this.onEvent(event); } public void triggerConnectionReconnectedEvent() { if (connection.getEventListener() == null) { return; } String brokerAddr = connection.getBrokerAddress(); String evCode = ConnectionReconnectedEvent.CONNECTION_RECONNECTED; String evMessage = ClientResources.getResources().getKString(evCode, brokerAddr); ConnectionReconnectedEvent event = new ConnectionReconnectedEvent(connection, evCode, evMessage); this.onEvent(event); } public void triggerConnectionExitEvent(JMSException jmse, ExceptionListener listener) { try { if (connection.getEventListener() == null) { return; } this.exlistener = listener; // this event is for MQ internal use only. This triggered the event // handler to call connection exception handler. ConnectionExitEvent event = new ConnectionExitEvent(connection, ConnectionExitEvent.CONNECTION_EXIT, jmse.getMessage(), jmse); this.onEvent(event); } catch (Exception ex) { ex.printStackTrace(Debug.getPrintStream()); } } public void triggerConnectionAddressListChangedEvent(String addrList) { if (connection.getEventListener() == null) { return; } String evCode = BrokerAddressListChangedEvent.CONNECTION_ADDRESS_LIST_CHANGED; String evMessage = ClientResources.getResources().getKString(evCode, addrList); BrokerAddressListChangedEvent event = new BrokerAddressListChangedEvent(connection, evCode, evMessage, addrList); this.onEvent(event); } public void triggerConsumerEvent(int infoType, String destName, int destType) { String evCode = null; switch (infoType) { case CONSUMER_NOT_READY: evCode = ConsumerEvent.CONSUMER_NOT_READY; break; case CONSUMER_READY: evCode = ConsumerEvent.CONSUMER_READY; break; default: Debug.println("Received unknown consumer event: " + infoType + " on destination " + destName); return; } String evMessage = ClientResources.getResources().getKString(evCode, (DestType.isQueue(destType) ? DestType.toString(DestType.DEST_TYPE_QUEUE) : DestType.toString(DestType.DEST_TYPE_TOPIC)) + ":" + destName); synchronized (consumerEventListeners) { Iterator itr = consumerEventListeners.keySet().iterator(); com.sun.messaging.Destination d = null; while (itr.hasNext()) { d = itr.next(); if (d.getName().equals(destName) && d.isQueue() == DestType.isQueue(destType) && d.isTemporary() == DestType.isTemporary(destType)) { this.onEvent((new ConsumerEvent(d, connection, evCode, evMessage))); return; } } } Debug.println("Listener not found for consumer INFO: " + evMessage); } public void resendConsumerInfoRequests(ProtocolHandler ph) throws JMSException { synchronized (consumerEventListeners) { Iterator itr = consumerEventListeners.keySet().iterator(); com.sun.messaging.Destination d = null; while (itr.hasNext()) { d = itr.next(); ph.requestConsumerInfo(d, false); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy