User: starksm
Date: 01/09/25 20:11:30
Added: catalina/src/main/org/jboss/web/catalina
EmbeddedCatalinaServiceSX.java
EmbeddedCatalinaServiceSXMBean.java
Log4jLogger.java
Log:
Initial version of Tomcat4.0/Catalina embedded service with full JNDI
and security integration
Revision Changes Path
1.1
contrib/catalina/src/main/org/jboss/web/catalina/EmbeddedCatalinaServiceSX.java
Index: EmbeddedCatalinaServiceSX.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web.catalina;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.io.PrintWriter;
import java.net.UnknownHostException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.net.InetAddress;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Iterator;
import javax.naming.InitialContext;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.jboss.ejb.DeploymentException;
import org.jboss.security.SecurityDomain;
import org.jboss.web.AbstractWebContainer;
import org.jboss.web.AbstractWebContainer.WebDescriptorParser;
import org.jboss.web.WebApplication;
import org.jboss.web.catalina.security.JBossSecurityMgrRealm;
import org.jboss.web.catalina.security.SSLServerSocketFactory;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.catalina.Connector;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Deployer;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Logger;
import org.apache.catalina.Realm;
import org.apache.catalina.connector.http.HttpConnector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappClassLoader;
import org.apache.catalina.startup.Embedded;
/** An implementation of the AbstractWebContainer for the Jakarta Tomcat
4.0 servlet container. This uses the Embedded as the integration class. It
does not parse the catalina server.xml.
@see org.jboss.web.AbstractWebContainer
@see org.apache.catalina.startup.Embedded
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
*/
public class EmbeddedCatalinaServiceSX extends AbstractWebContainer implements
EmbeddedCatalinaServiceSXMBean
{
// Constants -----------------------------------------------------
public static final String NAME = "EmbeddedCatalinaSX";
/** The embedded instance used to configure catalina */
private Embedded catalina;
/** The catalina host container */
private Host catalinaHost;
/** The catalina debug level */
private int debugLevel;
/** The path for the appbase for the root context */
private String webAppsRoot = "webapps/ROOT";
/** The port the web server listens on */
private int port = 8080;
/** The interface to bind to. This is useful for multi-homed hosts
that want control over which interfaces accept connections. */
private InetAddress bindAddress;
/** The accept count for this Connector. */
private int acceptCount = 10;
/** The "enable DNS lookups" flag. */
private boolean enableLookups = false;
/** The minimum number of processors to start at initialization time. */
protected int minProcessors = 5;
/**The maximum number of processors allowed, or <0 for unlimited. */
private int maxProcessors = 20;
/** The JNDI name of the SecurityDomain implementation binding */
private String securityDomain;
public EmbeddedCatalinaServiceSX()
{
}
public String getName()
{
return NAME;
}
public void setPort(int port)
{
this.port = port;
}
public int getPort()
{
return port;
}
public String getBindAddress()
{
String address = "0.0.0.0";
if( bindAddress != null )
address = bindAddress.getHostAddress();
return address;
}
public void setBindAddress(String host) throws UnknownHostException
{
if( host == null || host.length() == 0 )
bindAddress = null;
else
bindAddress = InetAddress.getByName(host);
}
public String getWebAppsRoot()
{
return webAppsRoot;
}
public void setWebAppsRoot(String webAppsRoot)
{
this.webAppsRoot = webAppsRoot;
}
public int getMinProcessors()
{
return this.minProcessors;
}
public void setMinProcessors(int minProcessors)
{
this.minProcessors = minProcessors;
}
public int getMaxProcessors()
{
return this.maxProcessors;
}
public void setMaxProcessors(int maxProcessors)
{
this.maxProcessors = maxProcessors;
}
public int getAcceptCount()
{
return this.acceptCount;
}
public void setAcceptCount(int acceptCount)
{
this.acceptCount = acceptCount;
}
public boolean getEnableLookups()
{
return enableLookups;
}
public void setEnableLookups(boolean enableLookups)
{
this.enableLookups = enableLookups;
}
public String getSecurityDomain()
{
return this.securityDomain;
}
public void setSecurityDomain(String securityDomain)
{
this.securityDomain = securityDomain;
}
public void startService() throws Exception
{
category.info("Starting " + NAME + "....");
// Start create the embeded catalina container but don't let it overwrite the
thread class loader
URLClassLoader cl = (URLClassLoader)
Thread.currentThread().getContextClassLoader();
URLClassLoader parent = cl;
while( parent != null )
{
category.trace(parent);
URL[] urls = parent.getURLs();
for(int u = 0; u < urls.length; u ++)
category.trace(" "+urls[u]);
parent = (URLClassLoader) parent.getParent();
}
// Determine the catalina debug level from the enabled priority
debugLevel = 0;
if( category.isTraceEnabled() )
debugLevel = 2;
category.debug("Setting catalina debug level to: "+debugLevel);
try
{
// Set the catalina.home property from the Embedded class location
ProtectionDomain pd = Embedded.class.getProtectionDomain();
URL catalinaHome = pd.getCodeSource().getLocation();
String homePath = catalinaHome.getFile();
File homeDir = new File(homePath, "../../..");
homePath = homeDir.getCanonicalPath();
category.debug("Setting catalina.home to: " + homePath);
System.setProperty("catalina.home", homePath);
System.setProperty("catalina.base", homePath);
initCatalina(cl);
catalina.start();
}
finally
{
Thread.currentThread().setContextClassLoader(cl);
}
category.info("OK");
}
public void stopService()
{
if( catalina != null )
{
try
{
catalina.stop();
}
catch(Exception e)
{
}
}
}
/** Perform the tomcat specific deployment steps.
*/
protected WebApplication performDeploy(String ctxPath, String warUrl,
WebDescriptorParser webAppParser) throws Exception
{
category.info("deploy, ctxPath="+ctxPath+", warUrl="+warUrl);
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
URL url = new URL(warUrl);
WebApplication appInfo = createWebContext(ctxPath, url, webAppParser);
category.debug("Initialized: "+appInfo);
return appInfo;
}
/** Perform the tomcat specific deployment steps.
*/
public void performUndeploy(String warUrl) throws Exception
{
// find the javax.servlet.ServletContext in the repository
WebApplication appInfo = getDeployedApp(warUrl);
Context context = null;
if( appInfo != null )
context = (Context) appInfo.getAppData();
if(context == null)
throw new DeploymentException("URL " + warUrl + " is not deployed");
String ctxPath = context.getPath();
Deployer deployer = (Deployer) catalinaHost;
deployer.remove(ctxPath);
}
/** Create and configure a org.apache.catalina.startup.Embedded
instance. Currently we do not use the server.xml file as we obtain all
of the required customization from our mbean properties.
*/
private void initCatalina(ClassLoader parent) throws Exception
{
Logger jbossLog = new Log4jLogger(this.category);
Realm jbossRealm = new JBossSecurityMgrRealm();
catalina = new Embedded(jbossLog, jbossRealm);
catalina.setDebug(debugLevel);
catalina.setUseNaming(false);
String hostname = "localhost";
if( bindAddress != null )
hostname = bindAddress.getHostName();
Engine engine = catalina.createEngine();
engine.setDefaultHost(hostname);
catalinaHost = catalina.createHost(hostname, "");
engine.addChild(catalinaHost);
engine.setParentClassLoader(parent);
Context root = catalina.createContext("", webAppsRoot);
catalinaHost.addChild(root);
// Install the assembled container hierarchy
catalina.addEngine(engine);
// Assemble and install a connector for our port and address
HttpConnector connector = (HttpConnector)
catalina.createConnector(bindAddress, port, false);
// Set the connector properties
connector.setAcceptCount(acceptCount);
connector.setMinProcessors(minProcessors);
connector.setMaxProcessors(maxProcessors);
connector.setEnableLookups(enableLookups);
// Enable a secure connector if a security domain was specified
if( securityDomain != null )
{
connector.setScheme("https");
connector.setSecure(true);
InitialContext iniCtx = new InitialContext();
SecurityDomain domain = (SecurityDomain) iniCtx.lookup(securityDomain);
connector.setFactory(new SSLServerSocketFactory(domain));
}
catalina.addConnector(connector);
}
private WebApplication createWebContext(String ctxPath, URL warUrl,
final WebDescriptorParser webAppParser) throws IOException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
final WebApplication appInfo = new WebApplication(warUrl.getPath(), warUrl,
loader);
final StandardContext context = (StandardContext)
catalina.createContext(ctxPath, warUrl.getFile());
context.setParentClassLoader(loader);
/* We need to establish the JNDI ENC prior to the start of the web container
so that init on startup servlets are able to interact with their ENC. We
hook into the context lifecycle events to be notified of the start of the
context as this occurs before the servlets are started.
*/
context.addLifecycleListener(new LifecycleListener()
{
public void lifecycleEvent(LifecycleEvent event)
{
Object source = event.getSource();
if( source == context &&
event.getType().equals(Lifecycle.START_EVENT) )
{
category.debug("Context.lifecycleEvent, event="+event);
contextInit(context, appInfo, webAppParser);
}
}
}
);
// A debug level of 1 is rather verbose so only enable debugging if trace
priority is active
if( debugLevel <= 1 )
context.setDebug(0);
catalinaHost.addChild(context);
return appInfo;
}
/** Build the web application ENC.
*/
private void contextInit(Context context, WebApplication appInfo,
WebDescriptorParser webAppParser)
{
try
{
InputStream stream = null;
ServletContext servletCtx = context.getServletContext();
if (servletCtx == null)
return;
stream = servletCtx.getResourceAsStream("/WEB-INF/web.xml");
if( stream == null )
{
category.warn("No /WEB-INF/web.xml descriptor found");
return;
}
// Get the web-app.xml and jboss-web.xml deployment descriptors
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
parser.setEntityResolver(new LocalResolver());
Document webDoc = parser.parse(stream);
Element web = webDoc.getDocumentElement();
Element jbossWeb = null;
stream = servletCtx.getResourceAsStream("/WEB-INF/jboss-web.xml");
if( stream != null )
{
Document jbossWebDoc = parser.parse(stream);
jbossWeb = jbossWebDoc.getDocumentElement();
}
// Setup the wep app JNDI java:comp/env namespace
ClassLoader scl = context.getLoader().getClassLoader();
webAppParser.parseWebAppDescriptors(scl, web, jbossWeb);
// Create a web application info object
appInfo.setWebApp(web);
appInfo.setJbossWeb(jbossWeb);
appInfo.setAppData(context);
}
catch(Exception e)
{
category.error("Failed to setup web application ENC", e);
}
}
/** An implementation of EntityResolver for the web.dtd and jboss-web.dtd
*/
private class LocalResolver implements EntityResolver
{
private HashMap dtds = new HashMap();
public LocalResolver()
{
dtds.put("-//jBoss//DTD Web Application 2.2//EN",
"org/jboss/metadata/jboss-web.dtd");
dtds.put("-//JBoss//DTD Web Application 2.3//EN",
"org/jboss/metadata/jboss-web.dtd");
dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",
"javax/servlet/resources/web-app_2_2.dtd");
dtds.put("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
"javax/servlet/resources/web-app_2_3.dtd");
}
public InputSource resolveEntity(String publicId, String systemId)
{
String dtd = (String) dtds.get(publicId);
InputSource is = null;
if (dtd != null)
{
try
{
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
InputStream dtdStream = loader.getResourceAsStream(dtd);
if( dtdStream == null )
category.warn("Failed to find local dtd: "+dtd);
else
is = new InputSource(dtdStream);
}
catch(Exception ignore)
{
// ignore
}
}
return is;
}
}
}
1.1
contrib/catalina/src/main/org/jboss/web/catalina/EmbeddedCatalinaServiceSXMBean.java
Index: EmbeddedCatalinaServiceSXMBean.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web.catalina;
import java.net.UnknownHostException;
import org.jboss.ejb.DeploymentException;
import org.jboss.web.AbstractWebContainerMBean;
/** Management interface for the embedded Catalina service.
*
* @author [EMAIL PROTECTED]
* @version $Revision: 1.1 $
*/
public interface EmbeddedCatalinaServiceSXMBean extends AbstractWebContainerMBean
{
/** @return the pathname to the document base directory
for the default context web application
*/
public String getWebAppsRoot();
/** Set the pathname to the document base directory
for the default context web application
@param docBase Absolute or relative pathname to the document base directory
* for default context web application
*/
public void setWebAppsRoot(String webAppsRoot);
/** Set the Catalina listening port.
@param part, the listening port, 0 == Anonymous.
*/
public void setPort(int port);
/** Get the Catalina listening port.
@return the Catalina listening port, 0 == Anonymous.
*/
public int getPort();
/** Get the specific address Catalina listens on.t
@return the interface name or IP address the WebService binds to.
*/
public String getBindAddress();
/** Set the specific address Catalina 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.
@param host, the interface name or IP address to bind. If host is null, or
has zero length, connections on any/all local addresses will be allowed.
*/
public void setBindAddress(String host) throws UnknownHostException;
/**@return the accept count for this Connector.
*/
public int getAcceptCount();
/**
* Set the accept count for this Connector.
*
* @param count The new accept count
*/
public void setAcceptCount(int count);
/**
* Return the minimum number of processors to start at initialization.
*/
public int getMinProcessors();
/**
* Set the minimum number of processors to start at initialization.
*
* @param minProcessors The new minimum processors
*/
public void setMinProcessors(int minProcessors);
/**
* Return the maximum number of processors allowed, or <0 for unlimited.
*/
public int getMaxProcessors();
/**
* Set the maximum number of processors allowed, or <0 for unlimited.
*
* @param maxProcessors The new maximum processors
*/
public void setMaxProcessors(int maxProcessors);
/** @return the "enable DNS lookups" flag.
*/
public boolean getEnableLookups();
/** Set the "enable DNS lookups" flag.
*
* @param enableLookups The "enable DNS lookups" flag value
*/
public void setEnableLookups(boolean enableLookups);
/** @return the JNDI name of the SecurityDomain instance to
use with JSSE.
*/
public String getSecurityDomain();
/** Set the JNDI name of the SecurityDomain instance to
use with JSSE.
* @param securityDomain the JNDI name of the SecurityDomain
instance to use with JSSE.
*/
public void setSecurityDomain(String securityDomain);
}
1.1
contrib/catalina/src/main/org/jboss/web/catalina/Log4jLogger.java
Index: Log4jLogger.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web.catalina;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import javax.servlet.ServletException;
import org.apache.catalina.Container;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Logger;
import org.apache.log4j.Category;
/**
*
* @author [EMAIL PROTECTED]
* @version
*/
public class Log4jLogger implements org.apache.catalina.Logger
{
/** The Container with which this Logger has been associated. */
protected Container container = null;
/** The property change support for this component. */
protected PropertyChangeSupport support = new PropertyChangeSupport(this);
/** The log4j Category */
Category category;
/** The verbosity level for above which log messages may be filtered. */
protected int verbosity = ERROR;
/** Creates new Log4jLogger */
public Log4jLogger(Category category)
{
this.category = category;
}
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener)
{
support.addPropertyChangeListener(listener);
}
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener)
{
support.removePropertyChangeListener(listener);
}
/**
* Return the Container with which this Logger has been associated.
*/
public Container getContainer()
{
return container;
}
/**
* Set the Container with which this Logger has been associated.
*
* @param container The associated Container
*/
public void setContainer(Container container)
{
Container oldContainer = this.container;
this.container = container;
support.firePropertyChange("container", oldContainer, this.container);
}
/**
* Return descriptive information about this Logger implementation and
* the corresponding version number, in the format
* <code><description>/<version></code>.
*/
public String getInfo()
{
return getClass().getName();
}
/**
* Return the verbosity level of this logger. Messages logged with a
* higher verbosity than this level will be silently ignored.
*/
public int getVerbosity()
{
return this.verbosity;
}
/**
* Set the verbosity level of this logger. Messages logged with a
* higher verbosity than this level will be silently ignored.
*
* @param verbosity The new verbosity level
*/
public void setVerbosity(int verbosity)
{
this.verbosity = verbosity;
}
public void setVerbosityLevel(String verbosity)
{
if ("FATAL".equalsIgnoreCase(verbosity))
this.verbosity = FATAL;
else if ("ERROR".equalsIgnoreCase(verbosity))
this.verbosity = ERROR;
else if ("WARNING".equalsIgnoreCase(verbosity))
this.verbosity = WARNING;
else if ("INFORMATION".equalsIgnoreCase(verbosity))
this.verbosity = INFORMATION;
else if ("DEBUG".equalsIgnoreCase(verbosity))
this.verbosity = DEBUG;
}
/**
* Writes the specified message to a servlet log file, usually an event
* log. The name and type of the servlet log is specific to the
* servlet container. This message will be logged unconditionally.
*
* @param message A <code>String</code> specifying the message to be
* written to the log file
*/
public void log(String message)
{
category.info(message);
}
/**
* Writes the specified exception, and message, to a servlet log file.
* The implementation of this method should call
* <code>log(msg, exception)</code> instead. This method is deprecated
* in the ServletContext interface, but not deprecated here to avoid
* many useless compiler warnings. This message will be logged
* unconditionally.
*
* @param exception An <code>Exception</code> to be reported
* @param message The associated message string
*/
public void log(Exception exception, String message)
{
category.error(message, exception);
}
/**
* Writes the specified message to the servlet log file, usually an event
* log, if the logger is set to a verbosity level equal to or higher than
* the specified value for this message.
*
* @param message A <code>String</code> specifying the message to be
* written to the log file
* @param verbosity Verbosity level of this message
*/
public void log(String message, int verbosity)
{
switch( verbosity )
{
case FATAL:
category.fatal(message);
break;
case ERROR:
category.error(message);
break;
case WARNING:
category.warn(message);
break;
case INFORMATION:
category.info(message);
break;
case DEBUG:
category.debug(message);
break;
}
}
/**
* Writes an explanatory message and a stack trace for a given
* <code>Throwable</code> exception to the servlet log file. The name
* and type of the servlet log file is specific to the servlet container,
* usually an event log. This message will be logged unconditionally.
*
* @param message A <code>String</code> that describes the error or
* exception
* @param throwable The <code>Throwable</code> error or exception
*/
public void log(String message, Throwable throwable)
{
Throwable rootCause = null;
if (throwable instanceof LifecycleException)
rootCause = ((LifecycleException) throwable).getThrowable();
else if (throwable instanceof ServletException)
rootCause = ((ServletException) throwable).getRootCause();
category.error(message, throwable);
if( rootCause != null )
{
category.error("----- Root Cause -----", rootCause);
}
}
/**
* Writes the specified message and exception to the servlet log file,
* usually an event log, if the logger is set to a verbosity level equal
* to or higher than the specified value for this message.
*
* @param message A <code>String</code> that describes the error or
* exception
* @param throwable The <code>Throwable</code> error or exception
* @param verbosity Verbosity level of this message
*/
public void log(String message, Throwable throwable, int verbosity)
{
switch( verbosity )
{
case FATAL:
category.fatal(message, throwable);
break;
case ERROR:
category.error(message, throwable);
break;
case WARNING:
category.warn(message, throwable);
break;
case INFORMATION:
category.info(message, throwable);
break;
case DEBUG:
category.debug(message, throwable);
break;
}
}
}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development