/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.mx.remoting;
import java.util.StringTokenizer;
import javax.management.MBeanServer;
import org.jboss.logging.Logger;
import org.jboss.remoting.ConnectionFailedException;
import org.jboss.remoting.InvokerLocator;
import org.jboss.remoting.ident.Identity;
/**
* MBeanTransportPreference is a utility class that will take into account the VM's setup transport
* preferences when trying to create a preferred connection back to a remote MBeanServer. Since there
* are cases when multiple invoker transports can exist and all be valid, this will help determine which
* order the transports should be attempted. You wouldn't want to connect via SOAP, in most cases, when
* TCP/IP via Sockets is available. There are cases however you do want to explicitly choose SOAP vs.
* Sockets or RMI, and in which case your preference order might be <tt>soap, socket, rmi.</tt>
*
* @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
* @version $Revision: 81023 $
*/
public class MBeanTransportPreference
{
private static final transient Logger log = Logger.getLogger(MBeanTransportPreference.class.getName());
// NOTE: we need to maybe think this through on how this really should work long term..
private static String _preferences = System.getProperty("jboss.transport.preferences", "socket,rmi,soap");
private static String preferences[] = initialize(_preferences);
private static MBeanServer ourServer;
private static Identity ourIdentity;
public static void setLocalServer(MBeanServer server, Identity identity)
{
if(log.isTraceEnabled())
{
log.trace("setLocalServer called - server=" + server + ",identity=" + identity);
}
ourServer = server;
ourIdentity = identity;
}
private static String[] initialize(String list)
{
if(list == null)
{
return new String[1];
}
StringTokenizer tok = new StringTokenizer(list, ",");
String pref [] = new String[tok.countTokens()];
int c = 0;
while(tok.hasMoreTokens())
{
String token = tok.nextToken();
pref[c++] = token.trim();
}
return pref;
}
/**
* set the order to use when selecting transports to connect to a remote server
*
* @param order
*/
public static void setTransportPreferences(String order[])
{
preferences = (order == null || order.length <= 0) ? initialize(_preferences) : order;
}
/**
* get the order to use when selecting transports to connect to a remote server
*
* @return
*/
public static String[] getTransportPreferences()
{
return preferences;
}
/**
* return a server transport to a MBeanServer on a remote server, using the transport
* preference order specified by the user
*
* @param identity
* @param locators
* @return
* @throws ConnectionFailedException
*/
public static MBeanServer getServerByTransport(Identity identity, InvokerLocator locators[])
throws ConnectionFailedException
{
if(log.isTraceEnabled())
{
log.trace("getServerByTransport for identity=" + identity + ", ours is=" + ourIdentity);
}
if(ourIdentity == null)
{
if(ourServer == null)
{
ourServer = JMXUtil.getMBeanServer();
}
ourIdentity = Identity.get(ourServer);
}
if(identity.isSameJVM(ourIdentity))
{
return ourServer;
}
for(int c = 0; c < preferences.length; c++)
{
String transport = preferences[c];
if(transport != null)
{
for(int x = 0; x < locators.length; x++)
{
if(locators[x].getProtocol().equals(transport))
{
// attempt connect to this first one in our pref list
try
{
MBeanServer svr = MBeanServerRegistry.getMBeanServerFor(locators[x]);
if(svr != null)
{
return svr;
}
svr = MBeanServerClientInvokerProxy.create(locators[x], ourIdentity.getJMXId(), identity.getJMXId());
if(svr != null)
{
return svr;
}
}
catch(Throwable ex)
{
}
}
}
}
}
for(int x = 0; x < locators.length; x++)
{
// attempt connect to this first one in our pref list
try
{
if(log.isTraceEnabled())
{
log.trace("attempting to connect via locator[" + x + "] (" + locators[x] + ") to: " + identity);
}
MBeanServer svr = MBeanServerRegistry.getMBeanServerFor(locators[x]);
if(svr != null)
{
return svr;
}
svr = MBeanServerClientInvokerProxy.create(locators[x], ourIdentity.getJMXId(), identity.getJMXId());
if(svr != null)
{
return svr;
}
}
catch(Throwable ex)
{
log.debug("Error connecting ... ", ex);
}
}
throw new ConnectionFailedException("No transport/connection available to connect to: " + identity);
}
}