/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, 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.web;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.jboss.bootstrap.api.as.config.JBossASServerConfig;
import org.jboss.config.ServerConfigUtil;
import org.jboss.system.ServiceMBeanSupport;
/**
* The WebService implementation. It configures a WebServer instance to
* perform dynamic class and resource loading.
*
* @jmx:mbean
* extends="org.jboss.system.ServiceMBean"
* name="jboss:service=WebService"
*
* @version <tt>$Revision: 109975 $</tt>
* @author <a href="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
* @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
*/
public class WebService extends ServiceMBeanSupport
implements WebServiceMBean
{
//
// jason: WebService and WebServer classes should be merged into one
// WebService only provides a thin layer of JMX which WebServer
// can do just as well.
//
// Doing so will dramatically simplify this component.
//
// Rename to HTTPClassLoaderService to be clear that this is not
// a fully functional web server.
//
/**
* The web server instance which does the work.
* <p>
* Note: This value shadows the MBeanServer server value
* from ServiceMBeanSupport.
*/
private WebServer server = new WebServer();
/** The host portion of the RMI codebase URL */
private String host;
/**
* @jmx:managed-constructor
*/
public WebService()
{
super();
}
/**
* @jmx:managed-operation
*/
public URL addClassLoader(ClassLoader cl)
{
return server.addClassLoader(cl);
}
/**
* @jmx:managed-operation
*/
public void removeClassLoader(ClassLoader cl)
{
server.removeClassLoader(cl);
}
/**
* Set the WebService listening port.
*
* @jmx:managed-attribute
*
* @param port The listening port; 0 for anonymous
*/
public void setPort(int port)
{
server.setPort(port);
}
/**
* Get the WebService listening port.
*
* @jmx:managed-attribute
*/
public int getPort()
{
return server.getPort();
}
/**
* Set the name of the interface to use for the host portion of the
* RMI codebase URL.
*
* @jmx:managed-attribute
*/
public void setHost(final String hostname)
{
this.host = ServerConfigUtil.fixRemoteAddress(hostname);
}
/**
* Get the name of the interface to use for the host portion of the
* RMI codebase URL.
*
* @jmx:managed-attribute
*/
public String getHost()
{
return host;
}
/**
* Set the specific address the WebService listens on. This can be used on
* a multi-homed host for a ServerSocket that will only accept connect requests
* to one of its addresses.
*
* @jmx:managed-attribute
*
* @param address the interface name or IP address to bind. If host is null,
* connections on any/all local addresses will be allowed.
*/
public void setBindAddress(String address) throws UnknownHostException
{
InetAddress bindAddress = toInetAddress(address);
server.setBindAddress(bindAddress);
}
/**
* Get the specific address the WebService listens on.
*
* @jmx:managed-attribute
*
* @return the interface name or IP address the WebService binds to.
*/
public String getBindAddress()
{
InetAddress bindAddress = server.getBindAddress();
if (bindAddress != null)
return bindAddress.getHostAddress();
else
return null;
}
/**
* Get the WebService listen queue backlog limit. The maximum queue length
* for incoming connection indications (a request to connect) is set to the
* backlog parameter. If a connection indication arrives when the queue is
* full, the connection is refused.
*
* @jmx:managed-attribute
*
* @return the queue backlog limit.
*/
public int getBacklog()
{
return server.getBacklog();
}
/**
* Set the WebService listen queue backlog limit. The maximum queue length
* for incoming connection indications (a request to connect) is set to the
* backlog parameter. If a connection indication arrives when the queue is
* full, the connection is refused.
*
* @jmx:managed-attribute
*
* @param backlog, the queue backlog limit.
*/
public void setBacklog(int backlog)
{
server.setBacklog(backlog);
}
/** Set the thread pool used for the WebServer class loading.
* @jmx:managed-attribute
*
*/
public void setExecutor(Executor executor)
{
server.setThreadPool(executor);
}
/**
* A flag indicating if the server should attempt to download classes from
* thread context class loader when a request arrives that does not have a
* class loader key prefix.
*
* @jmx:managed-attribute
*/
public boolean getDownloadServerClasses()
{
return server.getDownloadServerClasses();
}
/**
* @jmx:managed-attribute
*/
public void setDownloadServerClasses(boolean flag)
{
server.setDownloadServerClasses(flag);
}
/**
* A flag indicating if the server should attempt to download resources,
* i.e. resource paths that don't end in .class
*
* @jmx:managed-attribute
*/
public boolean getDownloadResources()
{
return server.getDownloadResources();
}
/**
* @jmx:managed-attribute
*/
public void setDownloadResources(boolean flag)
{
server.setDownloadResources(flag);
}
/**
* The RMI codebase URL.
*
* @jmx:managed-attribute
*/
public String getCodebase()
{
return System.getProperty("java.rmi.server.codebase");
}
protected ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException
{
return name == null ? OBJECT_NAME : name;
}
protected void createService() throws Exception
{
// Load the file mime.types into the mapping list
Properties mimeTypes = new Properties();
try
{
mimeTypes.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("org/jboss/web/mime.types"));
Enumeration keys = mimeTypes.keys();
while (keys.hasMoreElements())
{
String extension = (String) keys.nextElement();
String type = mimeTypes.getProperty(extension);
server.addMimeType(extension, type);
}
}
catch (Exception e)
{
log.error("Failed to load org/jboss/web/mime.types; ignoring", e);
}
// if no override has been specified, default to the jboss bind address
if (getBindAddress() == null)
setBindAddress(System.getProperty(JBossASServerConfig.PROP_KEY_JBOSSAS_BIND_ADDRESS));
// if no host specified, default to the java.rmi.server.hostname property value
if (getHost() == null)
setHost(System.getProperty("java.rmi.server.hostname"));
// Set the rmi codebase if it is not already set
String codebase = getCodebase();
if (codebase == null)
{
// JBAS-8540
codebase = "http://" + ServerConfigUtil.fixHostnameForURL(getHost()) + ":" + getPort() + "/";
System.setProperty("java.rmi.server.codebase", codebase);
}
log.info("Using RMI server codebase: " + codebase);
}
/**
* Start the web server for dynamic downloading of classes and resources.
*
* <p>
* The system <tt>java.rmi.server.codebase</tt> is also set to
* <em>http://<host>:<port>/</em> if the property has not been set.
*/
protected void startService() throws Exception
{
// Start the WebServer running
server.start();
// JBAS-8540
log.debug("Started WebServer with address: " + ServerConfigUtil.fixHostnameForURL(getBindAddress()) + ":" + getPort());
}
protected void stopService() throws Exception
{
server.stop();
// JBAS-8540
log.debug("Stopped WebServer with address: " + ServerConfigUtil.fixHostnameForURL(getBindAddress()) + ":" + getPort());
}
/**
* Safely convert a host string to InetAddress or null
*/
private InetAddress toInetAddress(String host) throws UnknownHostException
{
if (host == null || host.length() == 0)
return null;
else
return InetAddress.getByName(host);
}
}