@Override public void start() { embedded = new Tomcat(); AuthConfigFactory.setFactory(new AuthConfigFactoryImpl()); Context context = embedded.addContext(getContextPath(), "/"); context.addParameter("contextConfigLocation", getContextResource()); context.addApplicationListener(ContextLoaderListener.class.getName()); embedded.getHost().setAppBase(""); // Each servlet should get an unique name, otherwise all servers will reuse // one and the same servlet instance. Note that name clashes with servlets // created somewhere else are still possible. String servletName = getServletName() == null ? "ipf-servlet-" + SERVLET_COUNTER.getAndIncrement() : getServletName(); wrapper = context.createWrapper(); wrapper.setName(servletName); wrapper.setServletClass(getServlet().getClass().getName()); for (Map.Entry<String, String> parameters : getInitParameters().entrySet()) { wrapper.addInitParameter(parameters.getKey(), parameters.getValue()); } context.addChild(wrapper); context.addServletMapping(getServletPath(), servletName); /* VirtualWebappLoader loader = new VirtualWebappLoader(this.getClass().getClassLoader()); loader.setVirtualClasspath(System.getProperty("java.class.path")); context.setLoader(loader); */ Connector connector = embedded.getConnector(); connector.setPort(getPort()); if (isSecure()) { connector.setSecure(true); connector.setScheme("https"); connector.setProperty("SSLEnabled", "true"); connector.setProperty("sslProtocol", "TLS"); connector.setProperty("keystoreFile", getKeystoreFile()); connector.setProperty("keystorePass", getKeystorePass()); connector.setProperty("truststoreFile", getTruststoreFile()); connector.setProperty("truststorePass", getTruststorePass()); if (getClientAuthType() == ClientAuthType.MUST) { connector.setProperty("clientAuth", "true"); } else if (getClientAuthType() == ClientAuthType.WANT) { connector.setProperty("clientAuth", "want"); } } try { embedded.start(); wrapper.allocate(); log.info("Started embedded Tomcat server"); } catch (Exception e) { throw new AssertionError(e); } }
/** * Serve the specified request, creating the corresponding response. After the first time a * particular servlet class is requested, it will be served directly (like any registered servlet) * because it will have been registered and mapped in our associated Context. * * @param request The servlet request we are processing * @param response The servlet response we are creating * @exception IOException if an input/output error occurs * @exception ServletException if a servlet-specified error occurs */ public void serveRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Disallow calling this servlet via a named dispatcher if (request.getAttribute(Globals.NAMED_DISPATCHER_ATTR) != null) throw new ServletException(sm.getString("invokerServlet.notNamed")); // Identify the input parameters and our "included" state String inRequestURI = null; String inServletPath = null; String inPathInfo = null; boolean included = (request.getAttribute(Globals.REQUEST_URI_ATTR) != null); if (included) { inRequestURI = (String) request.getAttribute(Globals.REQUEST_URI_ATTR); inServletPath = (String) request.getAttribute(Globals.SERVLET_PATH_ATTR); inPathInfo = (String) request.getAttribute(Globals.PATH_INFO_ATTR); } else { inRequestURI = request.getRequestURI(); inServletPath = request.getServletPath(); inPathInfo = request.getPathInfo(); } if (debug >= 1) { log("included='" + included + "', requestURI='" + inRequestURI + "'"); log(" servletPath='" + inServletPath + "', pathInfo='" + inPathInfo + "'"); } // Make sure a servlet name or class name was specified if (inPathInfo == null) { if (debug >= 1) log("Invalid pathInfo '" + inPathInfo + "'"); if (included) throw new ServletException(sm.getString("invokerServlet.invalidPath", inRequestURI)); else { response.sendError(HttpServletResponse.SC_NOT_FOUND, inRequestURI); return; } } // Identify the outgoing servlet name or class, and outgoing path info String pathInfo = inPathInfo; String servletClass = pathInfo.substring(1); int slash = servletClass.indexOf('/'); // if (debug >= 2) // log(" Calculating with servletClass='" + servletClass + // "', pathInfo='" + pathInfo + "', slash=" + slash); if (slash >= 0) { pathInfo = servletClass.substring(slash); servletClass = servletClass.substring(0, slash); } else { pathInfo = ""; } if (servletClass.startsWith("org.apache.catalina")) { response.sendError(HttpServletResponse.SC_NOT_FOUND, inRequestURI); return; } if (debug >= 1) log("Processing servlet '" + servletClass + "' with path info '" + pathInfo + "'"); String name = "org.apache.catalina.INVOKER." + servletClass; String pattern = inServletPath + "/" + servletClass + "/*"; Wrapper wrapper = null; // Synchronize to avoid race conditions when multiple requests // try to initialize the same servlet at the same time synchronized (this) { // Are we referencing an existing servlet class or name? wrapper = (Wrapper) context.findChild(servletClass); if (wrapper == null) wrapper = (Wrapper) context.findChild(name); if (wrapper != null) { if (debug >= 1) log( "Using wrapper for servlet '" + wrapper.getName() + "' with mapping '" + pattern + "'"); context.addServletMapping(pattern, wrapper.getName()); } // No, create a new wrapper for the specified servlet class else { if (debug >= 1) log("Creating wrapper for '" + servletClass + "' with mapping '" + pattern + "'"); try { wrapper = context.createWrapper(); wrapper.setName(name); wrapper.setLoadOnStartup(1); wrapper.setServletClass(servletClass); context.addChild(wrapper); context.addServletMapping(pattern, name); } catch (Throwable t) { log(sm.getString("invokerServlet.cannotCreate", inRequestURI), t); context.removeServletMapping(pattern); context.removeChild(wrapper); if (included) throw new ServletException( sm.getString("invokerServlet.cannotCreate", inRequestURI), t); else { response.sendError(HttpServletResponse.SC_NOT_FOUND, inRequestURI); return; } } } } // Create a request wrapper to pass on to the invoked servlet InvokerHttpRequest wrequest = new InvokerHttpRequest(request); wrequest.setRequestURI(inRequestURI); StringBuffer sb = new StringBuffer(inServletPath); sb.append("/"); sb.append(servletClass); wrequest.setServletPath(sb.toString()); if ((pathInfo == null) || (pathInfo.length() < 1)) { wrequest.setPathInfo(null); wrequest.setPathTranslated(null); } else { wrequest.setPathInfo(pathInfo); wrequest.setPathTranslated(getServletContext().getRealPath(pathInfo)); } // Allocate a servlet instance to perform this request Servlet instance = null; try { // if (debug >= 2) // log(" Allocating servlet instance"); instance = wrapper.allocate(); } catch (ServletException e) { log(sm.getString("invokerServlet.allocate", inRequestURI), e); context.removeServletMapping(pattern); context.removeChild(wrapper); Throwable rootCause = e.getRootCause(); if (rootCause == null) rootCause = e; if (rootCause instanceof ClassNotFoundException) { response.sendError(HttpServletResponse.SC_NOT_FOUND, inRequestURI); return; } else if (rootCause instanceof IOException) { throw (IOException) rootCause; } else if (rootCause instanceof RuntimeException) { throw (RuntimeException) rootCause; } else if (rootCause instanceof ServletException) { throw (ServletException) rootCause; } else { throw new ServletException( sm.getString("invokerServlet.allocate", inRequestURI), rootCause); } } catch (Throwable e) { log(sm.getString("invokerServlet.allocate", inRequestURI), e); context.removeServletMapping(pattern); context.removeChild(wrapper); throw new ServletException(sm.getString("invokerServlet.allocate", inRequestURI), e); } // After loading the wrapper, restore some of the fields when including if (included) { wrequest.setRequestURI(request.getRequestURI()); wrequest.setPathInfo(request.getPathInfo()); wrequest.setServletPath(request.getServletPath()); } // Invoke the service() method of the allocated servlet try { String jspFile = wrapper.getJspFile(); if (jspFile != null) request.setAttribute(Globals.JSP_FILE_ATTR, jspFile); else request.removeAttribute(Globals.JSP_FILE_ATTR); request.setAttribute(Globals.INVOKED_ATTR, request.getServletPath()); // if (debug >= 2) // log(" Calling service() method, jspFile=" + // jspFile); instance.service(wrequest, response); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); } catch (IOException e) { // if (debug >= 2) // log(" service() method IOException", e); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); try { wrapper.deallocate(instance); } catch (Throwable f) {; } throw e; } catch (UnavailableException e) { // if (debug >= 2) // log(" service() method UnavailableException", e); context.removeServletMapping(pattern); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); try { wrapper.deallocate(instance); } catch (Throwable f) {; } throw e; } catch (ServletException e) { // if (debug >= 2) // log(" service() method ServletException", e); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); try { wrapper.deallocate(instance); } catch (Throwable f) {; } throw e; } catch (RuntimeException e) { // if (debug >= 2) // log(" service() method RuntimeException", e); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); try { wrapper.deallocate(instance); } catch (Throwable f) {; } throw e; } catch (Throwable e) { // if (debug >= 2) // log(" service() method Throwable", e); request.removeAttribute(Globals.INVOKED_ATTR); request.removeAttribute(Globals.JSP_FILE_ATTR); try { wrapper.deallocate(instance); } catch (Throwable f) {; } throw new ServletException("Invoker service() exception", e); } // Deallocate the allocated servlet instance try { // if (debug >= 2) // log(" deallocate servlet instance"); wrapper.deallocate(instance); } catch (ServletException e) { log(sm.getString("invokerServlet.deallocate", inRequestURI), e); throw e; } catch (Throwable e) { log(sm.getString("invokerServlet.deallocate", inRequestURI), e); throw new ServletException(sm.getString("invokerServlet.deallocate", inRequestURI), e); } }