Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if running servlet container is Eclipse Jetty

I try to detect if the application is running on Eclipse Jetty as servlet container. I found a solution for Mortbay Jetty , but not for the actual version from Eclipse. I modified the existing check and replaced the Classpath from "/org/mortbay/jetty/Server.class" to "/org/eclipse/jetty/server/Server.class" but the check fails on Jetty 9. Running the same application on tomcat was successful. What did I wrong?

The code looks like:

private boolean detect(final String clazz) {
  try {
    final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    systemClassLoader.loadClass(clazz);
    return true;
  } catch (final ClassNotFoundException cnfe) {
    final Class<?> classObj = getClass();
      if (classObj.getResource(clazz) != null) {
        return true;
  } else {
        return false;
      }
  }
}

Function called with:

detect("/org/eclipse/jetty/server/Server.class");
like image 371
DaSilva2010 Avatar asked Oct 22 '22 07:10

DaSilva2010


1 Answers

Accessing the server class can be done from embedded mode, but not a standalone Jetty. This is because the WebAppClassloader isolates access to the org.eclipse.jetty.server.Server class to webapps.

However, you can use the fact that all servlet container must have an implementation of the default servlet, just use the ServletContext to access the RequestDispatcher for the default servlet and pay attention to the implementation class name. Seems to work well on both Jetty 8.1.10 and 9.0.3 during embedded use. (will try again on standalone jetty shortly)

Full class as example:

package com.company.foo;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/detect" })
@SuppressWarnings("serial")
public class DetectServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        resp.setContentType("text/plain");
        PrintWriter out = resp.getWriter();
        detect(out,"org.eclipse.jetty.server.Server");
        detect(out,"/org/eclipse/jetty/server/Server.class");
        detect(out,"org.eclipse.jetty.server.Request");
        detect(out,"/org/eclipse/jetty/server/Request.class");
        detect(out,"org.mortbay.jetty.Server");
        detect(out,"/org/mortbay/jetty/Server.class");

        detectDefaultServlet(out, req, "org.eclipse.jetty");
        detectDefaultServlet(out, req, "org.apache.catalina");

        String version = getReflectedMethodValue("org.eclipse.jetty.server.Server", "getVersion");
        out.printf("Server.getVersion() = %s%n", version);
    }

    private void detectDefaultServlet(PrintWriter out, HttpServletRequest req, String keyword)
    {
        // Request the default servlet (its pretty safe to say it will always be there)
        RequestDispatcher dispatcher = req.getServletContext().getNamedDispatcher("default");
        if(dispatcher == null) {
            out.printf("detectDefaultServlet(out, req, \"%s\") = <no default servlet>%n", keyword);
            return;
        }

        // If the request dispatcher implementation contains the keyword, we can claim a match
        boolean detected = dispatcher.getClass().getName().contains(keyword);
        out.printf("detectDefaultServlet(out, req, \"%s\") = %b (%s)%n", keyword, detected, dispatcher.getClass().getName());
    }

    private String getReflectedMethodValue(String clazzName, String methodName)
    {
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        try
        {
            Class<?> clazz = Class.forName(clazzName,false,loader);
            Class<?> parameterTypes[] = new Class<?>[0];
            Method method = clazz.getDeclaredMethod(methodName,parameterTypes);
            Object args[] = new Object[0];
            return (String)method.invoke(clazz,args);
        }
        catch (ClassNotFoundException e)
        {
            return "<class-not-found>";
        }
        catch (Throwable t)
        {
            return "<" + t.getClass().getName() + ": " + t.getMessage() + ">";
        }
    }

    private void detect(PrintWriter out, String resource)
    {
        out.printf("detect(\"%s\") = %b%n",resource,detected(resource));
    }

    private boolean detected(String clazz)
    {
        try
        {
            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

            systemClassLoader.loadClass(clazz);

            return true;
        }
        catch (ClassNotFoundException cnfe)
        {
            Class<?> classObj = getClass();

            if (classObj.getResource(clazz) != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

Which will produce the following output on Jetty 8.1.10 Embedded

detect("org.eclipse.jetty.server.Server") = true
detect("/org/eclipse/jetty/server/Server.class") = true
detect("org.eclipse.jetty.server.Request") = true
detect("/org/eclipse/jetty/server/Request.class") = true
detect("org.mortbay.jetty.Server") = false
detect("/org/mortbay/jetty/Server.class") = false
detectDefaultServlet(out, req, "org.eclipse.jetty") = true (org.eclipse.jetty.server.Dispatcher)
detectDefaultServlet(out, req, "org.apache.catalina") = false (org.eclipse.jetty.server.Dispatcher)
Server.getVersion() = 8.1.10.v20130312

And similar output on Jetty 9.0.3 Embedded

detect("org.eclipse.jetty.server.Server") = true
detect("/org/eclipse/jetty/server/Server.class") = true
detect("org.eclipse.jetty.server.Request") = true
detect("/org/eclipse/jetty/server/Request.class") = true
detect("org.mortbay.jetty.Server") = false
detect("/org/mortbay/jetty/Server.class") = false
detectDefaultServlet(out, req, "org.eclipse.jetty") = true (org.eclipse.jetty.server.Dispatcher)
detectDefaultServlet(out, req, "org.apache.catalina") = false (org.eclipse.jetty.server.Dispatcher)
Server.getVersion() = 9.0.3.v20130506

But different for Jetty 9.0.3 Standalone

detect("org.eclipse.jetty.server.Server") = false
detect("/org/eclipse/jetty/server/Server.class") = false
detect("org.eclipse.jetty.server.Request") = false
detect("/org/eclipse/jetty/server/Request.class") = false
detect("org.mortbay.jetty.Server") = false
detect("/org/mortbay/jetty/Server.class") = false
detectDefaultServlet(out, req, "org.eclipse.jetty") = true (org.eclipse.jetty.server.Dispatcher)
detectDefaultServlet(out, req, "org.apache.catalina") = false (org.eclipse.jetty.server.Dispatcher)
Server.getVersion() = <class-not-found>
like image 154
Joakim Erdfelt Avatar answered Oct 30 '22 17:10

Joakim Erdfelt