Mladen Turk wrote:

-----Original Message-----
From: Remy Maucherat [mailto:[EMAIL PROTECTED]


Just wanted to let you know that the new embedded in 5.0 is great. Costin (and I, to some extent) got it running with JBoss 3.2 without any problem. The big advantage is that it's just like Tomcat standalone, except it also implements the Embedded API. The big trick however is that if the embbedding component uses JMX already, you can do everything using MBeans. It's really cool :)



Well that's great, can you send some cookbook?

I'd like to make a class for JK2 that will call the embedded TC from
_dirty_ JVM, something like LouncherBootstrap.
The class will be in that case be injected in JVM from class file itself
using DefineClass.


Here's the JBoss integration class. This should give you an idea. Note that the class can be compiled independently of TC 5. Zero coupling :)

Costin is awesome :-D
Well, except when he's doing build related stuff, of course ;-)

Remy
/*
 * JBoss, the OpenSource WebOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.web.catalina;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;

import org.jboss.deployment.DeploymentException;
import org.jboss.metadata.WebMetaData;
import org.jboss.util.file.JarUtils;
import org.jboss.web.AbstractWebContainer;
import org.jboss.web.AbstractWebContainer.WebDescriptorParser;
import org.jboss.web.WebApplication;

import javax.management.MBeanServerFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Attribute;

/** 
 * An implementation of the AbstractWebContainer for the Jakarta Tomcat5
 * servlet container. It has no code dependency on tomcat - only the new JMX
 * model is used.
 * 
 * Tomcat5 is organized as a set of mbeans - just like jboss.
 * 
 * @see AbstractWebContainer
 * 
 * @author [EMAIL PROTECTED]
 * @authro Costin Manolache
 * @version $Revision: 1.1.2.2 $
 */
public class Tomcat5 extends AbstractWebContainer
   implements Tomcat5MBean
{
    // Constants -----------------------------------------------------
    public static final String NAME = "EmbeddedTomcat5";

    // XXX We could make this configurable - so it can support other containers
    // that provide JMX-based deployment.
    private String contextClassName="org.apache.catalina.core.StandardContext";

    /** Domain for tomcat5 mbeans */
    private String catalinaDomain="Catalina";

    public Tomcat5()
    {
    }

    public String getName()
    {
        return NAME;
    }

    public String getDomain()
    {
        return this.catalinaDomain;
    }

    /** The most important atteribute - defines the managed domain.
     *  A catalina instance (engine) corresponds to a JMX domain, that's
     *  how we know where to deploy webapps.
     *
     * @param catalinaHome
     */
    public void setDomain(String catalinaHome)
    {
        this.catalinaDomain = catalinaHome;
    }

    public void setContextMBeanCode(String className) {
    }

    public String getContextMBeanCode() {
        return null;
    }


    public void startService() throws Exception
    {
        // Start create the embeded catalina container but don't let it overwrite the 
thread class loader
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        ClassLoader parent = cl;

        // This is a workaround for jasper - we need the jars in the repository.
        // Probably a better solution would be to fix jasper to better detect
        // the env.
        StringBuffer cp=new StringBuffer();
        String sep=System.getProperty("path.separator");
        while( parent != null )
        {
            log.trace(parent);
            URL[] urls = super.getClassLoaderURLs(parent);
            for(int u = 0; u < urls.length; u ++) {
                if( log.isTraceEnabled())
                    log.trace("  "+urls[u]);
                cp.append(sep).append( urls[u].getPath());
            }
            parent = parent.getParent();
        }
        System.setProperty("java.class.path", cp.toString());

        log.info("Setting classpath " + cp);

        // Other workarounds ???
        // Note that tomcat has its own life as a generic service - we don't
        // interfere, just deploy using regular plain JMX

        // Invoke the super method to register as a deployer
        super.startService();
    }

    public void stopService() throws Exception
    {
        super.stopService();
        // nothing special here - tomcat is started by an mbean service,
        // it has its own life
    }

    /** Perform the tomcat specific deployment steps.
     */
    protected void performDeploy(WebApplication appInfo, String warUrl,
                                 WebDescriptorParser webAppParser) throws Exception
    {
        WebMetaData metaData = appInfo.getMetaData();

        String ctxPath = metaData.getContextRoot();
        if( ctxPath.equals("/") || ctxPath.equals("/ROOT"))
        {
            log.info("deploy root context="+ctxPath);
            ctxPath = "";
            metaData.setContextRoot(ctxPath);
        }
        log.info("deploy, ctxPath="+ctxPath+", warUrl="+warUrl);

        URL url = new URL(warUrl);

        // Servlet engines needs a war in a dir so extract the nested war
        if( url.getProtocol().equals("njar") )
        {
            url = org.jboss.net.protocol.njar.Handler.njarToFile(url);
            log.debug("Extracted war from njar, warUrl="+url);
            File warFile = new File(url.getFile());
            String warFileName = warFile.getName();
            warFileName = warFileName.substring(0, warFileName.length()-3);
            warFileName += "war";
            File warDir = new File(warFile.getParent(), warFileName);
            FileInputStream warStream = new FileInputStream(warFile);
            JarUtils.unjar(warStream, warDir);
            warStream.close();
            log.debug("Unpacked war into dir: "+warDir);
            url = warDir.toURL();
        }

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        appInfo.setName(url.getPath());
        appInfo.setClassLoader(loader);
        appInfo.setURL(url);

        String hostName = metaData.getVirtualHost();

        if( ctxPath.equals("")) ctxPath="/";
        if( ctxPath.equals("/ROOT")) ctxPath="/";

        // XXX How do I find the j2eeApp name ???
        // XXX How can I find the jboss "id" if any ??
        String objectNameS=catalinaDomain + ":j2eeType=WebModule,name=//" +
                    ((hostName==null)?"localhost":hostName) + ctxPath +
                    ",j2eeApp=none,j2eeServer=jboss";

        ObjectName objectName=new ObjectName( objectNameS );

        MBeanServer server=getMBeanServer();

        if( server.isRegistered(objectName ) ) {
            // workaround
            server.invoke( objectName, "destroy", new Object[] {},
                        new String [] {});
            log.info("Already exists, unregistering " + objectName);
            server.unregisterMBean(objectName);
        }

        server.createMBean("org.apache.commons.modeler.BaseModelMBean",
                objectName, new Object[] {contextClassName},
                new String[] {"java.lang.String"});

        log.info("Setting docBase " + objectName );

        server.setAttribute( objectName, new Attribute("docBase", url.getFile()));

        // We want the webapp to see all the core classes. That's one easy way
        // Probably we need finer control in tomcat.
        server.setAttribute( objectName, new Attribute("privileged", Boolean.TRUE));

        server.setAttribute( objectName, new Attribute("defaultWebXml", "web.xml"));
        //      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. */
        // XXX TODO

        server.invoke( objectName, "init", new Object[]{}, new String[] {});
        //server.invoke( objectName, "start", new Object[]{}, new String[] {});

        appInfo.setAppData( objectName );

        initENC(appInfo, webAppParser);

        log.debug("Initialized: "+appInfo+ " " + objectName);
    }

    /** Perform the tomcat specific deployment steps.
     */
    public void performUndeploy(String warUrl) throws Exception
    {
        WebApplication appInfo = getDeployedApp(warUrl);
        if( appInfo == null )
        {
            log.debug("performUndeploy, no WebApplication found for URL "+warUrl);
            return;
        }

        log.info("undeploy, ctxPath="+appInfo.getMetaData().getContextRoot()+", 
warUrl="+warUrl);

        Object context = (Object) appInfo.getAppData();

        if(context == null)
            throw new DeploymentException("URL " + warUrl + " is not deployed");

        MBeanServer server=getMBeanServer();
        server.invoke( (ObjectName)context, "destroy", new Object[] {},
                new String [] {});
        server.unregisterMBean((ObjectName)context);
    }

    /** Initialize the JNDI names from the web descriptor
     */
    private void initENC(WebApplication appInfo, WebDescriptorParser webAppParser)
            throws Exception
    {
        ClassLoader tcl = Thread.currentThread().getContextClassLoader();
        WebMetaData metaData = appInfo.getMetaData();
        webAppParser.parseWebAppDescriptors(tcl, metaData);
    }

//            /* We need to go through the context valves and set the cache flag
//             on any AuthenticatorBase to false or else the JBossSecurityMgrRealm
//             is not asked to authenticate every request. This can result in
//             an authenticated user thread not receiving its authenticated
//             Subject and this results in an authorization failure.
//             */
//            Valve[] valves = ((StandardContext)context).getValves();
//            for(int v = 0; v < valves.length; v ++)
//            {
//               Valve valve = valves[v];
//               if( valve instanceof AuthenticatorBase )
//               {
//                  AuthenticatorBase auth = (AuthenticatorBase) valve;
//                  auth.setCache(false);
//               }
//            }


//            // Add all of the classpth elements
//            ClassLoader rsrcLoader = Thread.currentThread().getContextClassLoader();
//            String[] jspCP = getCompileClasspath(rsrcLoader);
//            Loader ctxLoader = context.getLoader();
//            for(int u = 0; u < jspCP.length; u ++)
//            {
//               ctxLoader.addRepository(jspCP[u]);
//            }
//


//            // Setup the wep app JNDI java:comp/env namespace
//            ClassLoader scl = context.getLoader().getClassLoader();
//            // Enable parent delegation class loading
//            try
//            {
//               Class[] signature = {boolean.class};
//               Method setDelegate = scl.getClass().getMethod("setDelegate", 
signature);
//               Object[] args = {new Boolean(this.useParentDelegation)};
//               setDelegate.invoke(scl, args);
//               log.info("Using Java2 parent classloader delegation: 
"+useParentDelegation);
//            }

    private MBeanServer server;
    private MBeanServer getMBeanServer() {
        if (server == null) {
            if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
                server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
            } else {
                server=MBeanServerFactory.createMBeanServer();
            }
        }
        return server;
    }


}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to