/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink * cdelahun - Bug 214534: added JMS Cache Coordination for publishing only ******************************************************************************/ package org.eclipse.persistence.sessions.coordination.jms; import java.util.Map; import org.eclipse.persistence.exceptions.RemoteCommandManagerException; import org.eclipse.persistence.internal.sessions.coordination.RemoteConnection; import org.eclipse.persistence.internal.sessions.coordination.jms.JMSTopicRemoteConnection; import org.eclipse.persistence.sessions.coordination.RemoteCommandManager; /** * <p> * <b>Purpose</b>: Provide a transport implementation for the Remote Command Module (RCM) that both publishes * and subscribes to a JMS topic. * <p> * <b>Description</b>: This class manages two connections to the same known JMS Topic: * external connection for publishing, local connection for receiving messages. * <p> * @author Steven Vo * @since OracleAS TopLink 10<i>g</i> (10.0.3) */ public class JMSTopicTransportManager extends JMSPublishingTransportManager { public JMSTopicTransportManager(RemoteCommandManager rcm) { super(rcm); } /** * INTERNAL: * JMSTopicTransportManager may have only two connections: one local and one external. * In case the local connection doesn't exist, this method creates it. */ public synchronized void createLocalConnection() { if(localConnection == null) { try { localConnection = createConnection(true); } catch (RemoteCommandManagerException rcmException) { // to recover handle RemoteCommandManagerException.ERROR_CREATING_LOCAL_JMS_CONNECTION: // after changing something (for instance jmsHostUrl) // call createLocalConnection method again. rcm.handleException(rcmException); } } } /** * INTERNAL: * In case there's no external connection attempts to create one, * if that's successful then (in case there is no local connection, too) * attempts to create local connection in a separate thread. * Returns clone of the original map. */ public Map<String, RemoteConnection> getConnectionsToExternalServicesForCommandPropagation() { if (this.localConnection == null && !this.rcm.isStopped()) { // It's a good time to create localConnection, // in a new thread - to return externalConnections promptly. this.rcm.getServerPlatform().launchContainerRunnable(new Runnable() { public void run() { try { createLocalConnection(); } catch (RemoteCommandManagerException ex) { // Ignore exception - user had a chance to handle it in createLocalConnection method: // for instance to change host url and create a new local connection. } } }); } return super.getConnectionsToExternalServicesForCommandPropagation(); } /** * INTERNAL: * caches local connection, set localConnection to null, closes the cached connection in a new thread. */ public void removeLocalConnection() { JMSTopicRemoteConnection connectionToRemove = (JMSTopicRemoteConnection)localConnection; synchronized(this) { if(connectionToRemove == localConnection) { localConnection = null; } else { connectionToRemove = null; } } // closing connection may take time - do it outside of the synchronized block if(connectionToRemove != null) { connectionToRemove.close(); } } }