/*
* 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.invocation.http.server;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.RuntimeMBeanException;
import javax.management.RuntimeOperationsException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.Transaction;
import org.jboss.invocation.Invocation;
import org.jboss.invocation.Invoker;
import org.jboss.invocation.MarshalledInvocation;
import org.jboss.invocation.http.interfaces.HttpInvokerProxy;
import org.jboss.system.Registry;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.util.StringPropertyReplacer;
import org.jboss.config.ServerConfigUtil;
/**
* The HttpInvoker ... into the JMX base.
*
* @author <a href="mailto:scott.stark@jboss.org>Scott Stark</a>
* @version $Revision: 109975 $
*/
public class HttpInvoker extends ServiceMBeanSupport
implements HttpInvokerMBean
{
private String invokerURL;
private String invokerURLPrefix = "http://";
private String invokerURLSuffix = ":8080/invoker/JMXInvokerServlet";
private boolean useHostName = false;
// Public --------------------------------------------------------
public String getInvokerURL()
{
return invokerURL;
}
public void setInvokerURL(String invokerURL)
{
// Replace any system properties in the URL
String tmp = StringPropertyReplacer.replaceProperties(invokerURL);
this.invokerURL = tmp;
log.debug("Set invokerURL to "+this.invokerURL);
}
public String getInvokerURLPrefix()
{
return invokerURLPrefix;
}
public void setInvokerURLPrefix(String invokerURLPrefix)
{
this.invokerURLPrefix = invokerURLPrefix;
}
public String getInvokerURLSuffix()
{
return invokerURLSuffix;
}
public void setInvokerURLSuffix(String invokerURLSuffix)
{
this.invokerURLSuffix = invokerURLSuffix;
}
public boolean getUseHostName()
{
return useHostName;
}
public void setUseHostName(boolean flag)
{
this.useHostName = flag;
}
protected void startService()
throws Exception
{
checkInvokerURL();
Invoker delegateInvoker = new HttpInvokerProxy(invokerURL);
// Export the Invoker interface
ObjectName name = super.getServiceName();
Registry.bind(name, delegateInvoker);
log.debug("Bound Http invoker for JMX node");
}
protected void stopService()
{
try
{
InitialContext ctx = new InitialContext();
ctx.unbind("invokers/"+InetAddress.getLocalHost().getHostName()+"/http");
}
catch (NamingException ignore)
{
}
catch (Throwable e)
{
log.error("Failed", e);
return;
}
}
protected void destroyService()
{
// Export references to the bean
Registry.unbind(serviceName);
}
/**
* Invoke a Remote interface method.
*/
public Object invoke(Invocation invocation)
throws Exception
{
ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
try
{
// Deserialize the transaction if it is there
MarshalledInvocation mi = (MarshalledInvocation) invocation;
Object tpc = mi.getTransactionPropagationContext();
Transaction tx = importTPC(tpc);
invocation.setTransaction(tx);
Integer nameHash = (Integer) invocation.getObjectName();
ObjectName mbean = (ObjectName) Registry.lookup(nameHash);
// The cl on the thread should be set in another interceptor
Object[] args = {invocation};
String[] sig = {"org.jboss.invocation.Invocation"};
Object obj = super.getServer().invoke(mbean,
"invoke", args, sig);
// Return the raw object and let the http layer marshall it
return obj;
}
catch (Exception e)
{
if (e instanceof MBeanException)
e = ((MBeanException)e).getTargetException();
if (e instanceof RuntimeMBeanException)
e = ((RuntimeMBeanException)e).getTargetException();
if (e instanceof RuntimeOperationsException)
e = ((RuntimeOperationsException)e).getTargetException();
// Only log errors if trace is enabled
if( log.isTraceEnabled() )
log.trace("operation failed", e);
throw e;
}
finally
{
Thread.currentThread().setContextClassLoader(oldCl);
}
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
/** Not implemented, and should not be
*/
protected Transaction importTPC(Object tpc)
{
return null;
}
/** Validate that the invokerURL is set, and if not build it from
* the invokerURLPrefix + host + invokerURLSuffix. The host value will be
* taken from the jboss.bind.address system property if its a valid
* address, InetAddress.getLocalHost otherwise.
*/
protected void checkInvokerURL() throws UnknownHostException
{
if( invokerURL == null )
{
InetAddress addr = InetAddress.getLocalHost();
// First check for a global bind address
String host = ServerConfigUtil.getSpecificBindAddress();
if( host == null )
{
host = useHostName ? addr.getHostName() : addr.getHostAddress();
}
String url = invokerURLPrefix + ServerConfigUtil.fixHostnameForURL(host) + invokerURLSuffix;
setInvokerURL(url);
}
}
}