/** * onServletStart * * @param args */ @Override public void onServletStart(Object... args) { StandardWrapper sw = (StandardWrapper) args[0]; Servlet servlet = (Servlet) args[1]; InterceptSupport iSupport = InterceptSupport.instance(); InterceptContext context = iSupport.createInterceptContext(Event.AFTER_SERVET_INIT); context.put(InterceptConstants.SERVLET_INSTANCE, servlet); /** * NOTE: spring boot rewrite the tomcat webappclassloader, makes the addURL for nothing, then we can't do * anything on this we may use its webappclassloader's parent as the classloader */ context.put(InterceptConstants.WEBAPPLOADER, Thread.currentThread().getContextClassLoader().getParent()); context.put(InterceptConstants.CONTEXTPATH, sw.getServletContext().getContextPath()); iSupport.doIntercept(context); }
/** * onServletStop * * @param args */ @Override public void onServletStop(Object... args) { StandardWrapper sw = (StandardWrapper) args[0]; Servlet servlet = (Servlet) args[1]; InterceptSupport iSupport = InterceptSupport.instance(); InterceptContext context = iSupport.createInterceptContext(Event.BEFORE_SERVLET_DESTROY); context.put(InterceptConstants.SERVLET_INSTANCE, servlet); /** * NOTE: spring boot rewrite the tomcat webappclassloader, makes the addURL for nothing, then we can't do * anything on this we may use its webappclassloader's parent as the classloader */ context.put(InterceptConstants.WEBAPPLOADER, Thread.currentThread().getContextClassLoader().getParent()); context.put(InterceptConstants.CONTEXTPATH, sw.getServletContext().getContextPath()); iSupport.doIntercept(context); }
private static ServletInfo getServletInfo(Wrapper w, String contextName) { ServletInfo si = new ServletInfo(); si.setApplicationName(contextName.length() > 0 ? contextName : "/"); si.setServletName(w.getName()); si.setServletClass(w.getServletClass()); si.setAvailable(! w.isUnavailable()); si.setLoadOnStartup(w.getLoadOnStartup()); si.setRunAs(w.getRunAs()); String[] ms = w.findMappings(); for (int i = 0; i < ms.length; i++) { si.getMappings().add(ms[i]); } if (w instanceof StandardWrapper) { StandardWrapper sw = (StandardWrapper) w; si.setAllocationCount(sw.getCountAllocated()); si.setErrorCount(sw.getErrorCount()); si.setLoadTime(sw.getLoadTime()); si.setMaxInstances(sw.getMaxInstances()); si.setMaxTime(sw.getMaxTime()); si.setMinTime(sw.getMinTime() == Long.MAX_VALUE ? 0 : sw.getMinTime()); si.setProcessingTime(sw.getProcessingTime()); si.setRequestCount(sw.getRequestCount()); si.setSingleThreaded(sw.isSingleThreadModel()); } return si; }
public StandardWrapper addServlet(String contextPath, String servletName, String servletClass) { Container ctx = getHost().findChild(contextPath); return addServlet((StandardContext) ctx, servletName, servletClass); }
/** Use an existing servlet, no class.forName or initialization will be * performed */ public StandardWrapper addServlet(StandardContext ctx, String servletName, Servlet servlet) { // will do class for name and set init params StandardWrapper sw = new ExistingStandardWrapper(servlet); sw.setName(servletName); ctx.addChild(sw); return sw; }
/** * Construct a new instance of this class, configured according to the * specified parameters. If both servletPath and pathInfo are * <code>null</code>, it will be assumed that this RequestDispatcher * was acquired by name, rather than by path. * * @param wrapper The Wrapper associated with the resource that will * be forwarded to or included (required) * @param servletPath The revised servlet path to this resource (if any) * @param pathInfo The revised extra path information to this resource * (if any) * @param queryString Query string parameters included with this request * (if any) * @param name Servlet name (if a named dispatcher was created) * else <code>null</code> */ public ApplicationDispatcher (Wrapper wrapper, String servletPath, String pathInfo, String queryString, String name) { super(); // Save all of our configuration parameters this.wrapper = wrapper; this.context = (Context) wrapper.getParent(); this.servletPath = servletPath; this.pathInfo = pathInfo; this.queryString = queryString; this.name = name; if (wrapper instanceof StandardWrapper) this.support = ((StandardWrapper) wrapper).getInstanceSupport(); else this.support = new InstanceSupport(wrapper); if (debug >= 1) log("servletPath=" + this.servletPath + ", pathInfo=" + this.pathInfo + ", queryString=" + queryString + ", name=" + this.name); // If this is a wrapper for a JSP page (<jsp-file>), tweak // the request parameters appropriately String jspFile = wrapper.getJspFile(); if (jspFile != null) { if (debug >= 1) log("-->servletPath=" + jspFile); this.servletPath = jspFile; } }
/** * onServletStart * * @param args */ public void onServletStart(Object... args) { StandardWrapper sw = (StandardWrapper) args[0]; Servlet servlet = (Servlet) args[1]; InterceptSupport iSupport = InterceptSupport.instance(); InterceptContext context = iSupport.createInterceptContext(Event.AFTER_SERVET_INIT); context.put(InterceptConstants.SERVLET_INSTANCE, servlet); context.put(InterceptConstants.WEBAPPLOADER, Thread.currentThread().getContextClassLoader()); context.put(InterceptConstants.CONTEXTPATH, sw.getServletContext().getContextPath()); iSupport.doIntercept(context); }
/** * onServletStop * * @param args */ public void onServletStop(Object... args) { StandardWrapper sw = (StandardWrapper) args[0]; Servlet servlet = (Servlet) args[1]; InterceptSupport iSupport = InterceptSupport.instance(); InterceptContext context = iSupport.createInterceptContext(Event.BEFORE_SERVLET_DESTROY); context.put(InterceptConstants.SERVLET_INSTANCE, servlet); context.put(InterceptConstants.WEBAPPLOADER, Thread.currentThread().getContextClassLoader()); context.put(InterceptConstants.CONTEXTPATH, sw.getServletContext().getContextPath()); iSupport.doIntercept(context); }
/** * Calculates Sum of requestCount, errorCount and processingTime for all servlets for the given * application. It also works out minimum value of minTime and maximum value for maxTime for all * servlets. * * @param context the context whose stats will be collected * @param app the application in which to store the collected stats */ public static void collectApplicationServletStats(Context context, Application app) { int svltCount = 0; int reqCount = 0; int errCount = 0; long procTime = 0; long minTime = Long.MAX_VALUE; long maxTime = 0; for (Container container : context.findChildren()) { if (container instanceof StandardWrapper) { StandardWrapper sw = (StandardWrapper) container; svltCount++; reqCount += sw.getRequestCount(); errCount += sw.getErrorCount(); procTime += sw.getProcessingTime(); if (sw.getRequestCount() > 0) { minTime = Math.min(minTime, sw.getMinTime()); } maxTime = Math.max(maxTime, sw.getMaxTime()); } } app.setServletCount(svltCount); app.setRequestCount(reqCount); app.setErrorCount(errCount); app.setProcessingTime(procTime); app.setMinTime(minTime == Long.MAX_VALUE ? 0 : minTime); app.setMaxTime(maxTime); }
/** * Gets the servlet info. * * @param wrapper the wrapper * @param contextName the context name * @return the servlet info */ private static ServletInfo getServletInfo(Wrapper wrapper, String contextName) { ServletInfo si = new ServletInfo(); si.setApplicationName(contextName.length() > 0 ? contextName : "/"); si.setServletName(wrapper.getName()); si.setServletClass(wrapper.getServletClass()); si.setAvailable(!wrapper.isUnavailable()); si.setLoadOnStartup(wrapper.getLoadOnStartup()); si.setRunAs(wrapper.getRunAs()); si.getMappings().addAll(Arrays.asList(wrapper.findMappings())); if (wrapper instanceof StandardWrapper) { StandardWrapper sw = (StandardWrapper) wrapper; si.setAllocationCount(sw.getCountAllocated()); si.setErrorCount(sw.getErrorCount()); si.setLoadTime(sw.getLoadTime()); si.setMaxInstances(sw.getMaxInstances()); si.setMaxTime(sw.getMaxTime()); si.setMinTime(sw.getMinTime() == Long.MAX_VALUE ? 0 : sw.getMinTime()); si.setProcessingTime(sw.getProcessingTime()); si.setRequestCount(sw.getRequestCount()); // Tomcat 7.0.72+, 8.0.37+, 8.5.5+, and 9.0.0.M10 modified from boolean to Boolean. // Since SingleThreadModel deprecated in servlet 2.4 with no direct replacement, // we will continue to handle as boolean. Previously calling this would have // resulted in class being loaded if not already. This is why Null is returned // now. try { Object singleThreaded = MethodUtils.invokeMethod(sw, "isSingleThreadModel"); if (singleThreaded == null) { si.setSingleThreaded(false); } else { si.setSingleThreaded(Boolean.parseBoolean(String.valueOf(singleThreaded))); } } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { logger.error("Cannot determine single threading"); logger.trace("", e); } } return si; }
/** * Calculates Sum of requestCount, errorCount and processingTime for all servlets for the * give application. It also works out minimum value of minTime and maximum value for maxTime for * all servlets. * * @param context * @param app */ public static void collectApplicationServletStats(Context context, Application app) { int svltCount = 0; int reqCount = 0; int errCount = 0; long procTime = 0; long minTime = Long.MAX_VALUE; long maxTime = 0; Container[] cns = context.findChildren(); for (int i = 0; i < cns.length; i++) { if (cns[i] instanceof StandardWrapper) { StandardWrapper sw = (StandardWrapper) cns[i]; svltCount++; reqCount += sw.getRequestCount(); errCount += sw.getErrorCount(); procTime += sw.getProcessingTime(); if (sw.getRequestCount() > 0) { minTime = Math.min(minTime, sw.getMinTime()); } maxTime = Math.max(maxTime, sw.getMaxTime()); } } app.setServletCount(svltCount); app.setRequestCount(reqCount); app.setErrorCount(errCount); app.setProcessingTime(procTime); app.setMinTime(minTime == Long.MAX_VALUE ? 0 : minTime); app.setMaxTime(maxTime); }
public void onReload() throws ServletException { Context context = this.getContext(); Wrapper jspWrapper = (Wrapper)context.findChild("jsp"); // There might not be any jsps if we're just getting started. if (jspWrapper==null) return; jspWrapper.unload(); // tomcat-catalina 8.0.29 // This custom hack is required to fix a bug in the StandardWrapper catalina sourcecode. This custom field in their source was not reset back to false // after calling unload, so the underlying JspServlet (the instance) did not get initialized properly upon calling load. // This bug happens in tomcat 7 and 8. // https://bz.apache.org/bugzilla/show_bug.cgi?id=58701 AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { try { Field field = ((StandardWrapper)jspWrapper).getClass().getDeclaredField("instanceInitialized"); field.setAccessible(true); field.setBoolean(jspWrapper, false); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { throw new RuntimeException(e); } return Boolean.TRUE; } }); jspWrapper.load(); }
/** Init default servlets for the context. This should be the programmatic * equivalent of the default web.xml. * * TODO: in normal tomcat, if default-web.xml is not found, use this * method */ protected void initWebappDefaults(StandardContext ctx) { // Default servlet StandardWrapper servlet = addServlet(ctx, "default", //new DefaultServlet()); // Or: "org.apache.catalina.servlets.DefaultServlet"); servlet.addInitParameter("listings", "false"); servlet.setLoadOnStartup(1); // class name - to avoid loading all deps servlet = addServlet(ctx, "jsp", "org.apache.jasper.servlet.JspServlet"); servlet.addInitParameter("fork", "false"); servlet.addInitParameter("xpoweredBy", "false"); // in default web.xml - but not here, only needed if you have // jsps. //servlet.setLoadOnStartup(3); ctx.addServletMapping("/", "default"); ctx.addServletMapping("*.jsp", "jsp"); ctx.addServletMapping("*.jspx", "jsp"); // Sessions ctx.setManager( new StandardManager()); ctx.setSessionTimeout(30); // TODO: read mime from /etc/mime.types on linux, or some // resource for (int i = 0; i < DEFAULT_MIME_MAPPINGS.length; ) { ctx.addMimeMapping(DEFAULT_MIME_MAPPINGS[i++], DEFAULT_MIME_MAPPINGS[i++]); } ctx.addWelcomeFile("index.html"); ctx.addWelcomeFile("index.htm"); ctx.addWelcomeFile("index.jsp"); ctx.setLoginConfig( new LoginConfig("NONE", null, null, null)); // TODO: set a default realm, add simple API to add users }
public static void main(String[] args) { //invoke: http://localhost:8080/Modern or http://localhost:8080/Primitive System.setProperty("catalina.base", System.getProperty("user.dir")); Connector connector = new HttpConnector(); Wrapper wrapper1 = new StandardWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new StandardWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet"); Context context = new StandardContext(); // StandardContext's start method adds a default mapper context.setPath("/myApp"); context.setDocBase("myApp"); LifecycleListener listener = new SimpleContextConfig(); ((Lifecycle) context).addLifecycleListener(listener); context.addChild(wrapper1); context.addChild(wrapper2); // for simplicity, we don't add a valve, but you can add // valves to context or wrapper just as you did in Chapter 6 Loader loader = new WebappLoader(); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern"); // add ContextConfig. This listener is important because it configures // StandardContext (sets configured to true), otherwise StandardContext // won't start connector.setContainer(context); try { connector.initialize(); ((Lifecycle) connector).start(); ((Lifecycle) context).start(); // make the application wait until we press a key. System.in.read(); ((Lifecycle) context).stop(); } catch (Exception e) { e.printStackTrace(); } }
public static void main(String[] args) { //invoke: http://localhost:8080/app1/Primitive or http://localhost:8080/app1/Modern System.setProperty("catalina.base", System.getProperty("user.dir")); Connector connector = new HttpConnector(); Wrapper wrapper1 = new StandardWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new StandardWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet"); Context context = new StandardContext(); // StandardContext's start method adds a default mapper context.setPath("/app1"); context.setDocBase("app1"); context.addChild(wrapper1); context.addChild(wrapper2); LifecycleListener listener = new SimpleContextConfig(); ((Lifecycle) context).addLifecycleListener(listener); Host host = new StandardHost(); host.addChild(context); host.setName("localhost"); host.setAppBase("webapps"); Loader loader = new WebappLoader(); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern"); connector.setContainer(host); try { connector.initialize(); ((Lifecycle) connector).start(); ((Lifecycle) host).start(); // make the application wait until we press a key. System.in.read(); ((Lifecycle) host).stop(); } catch (Exception e) { e.printStackTrace(); } }
public static void main(String[] args) { //invoke: http://localhost:8080/app1/Primitive or http://localhost:8080/app1/Modern System.setProperty("catalina.base", System.getProperty("user.dir")); Connector connector = new HttpConnector(); Wrapper wrapper1 = new StandardWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new StandardWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet"); Context context = new StandardContext(); // StandardContext's start method adds a default mapper context.setPath("/app1"); context.setDocBase("app1"); context.addChild(wrapper1); context.addChild(wrapper2); LifecycleListener listener = new SimpleContextConfig(); ((Lifecycle) context).addLifecycleListener(listener); Host host = new StandardHost(); host.addChild(context); host.setName("localhost"); host.setAppBase("webapps"); Loader loader = new WebappLoader(); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern"); Engine engine = new StandardEngine(); engine.addChild(host); engine.setDefaultHost("localhost"); connector.setContainer(engine); try { connector.initialize(); ((Lifecycle) connector).start(); ((Lifecycle) engine).start(); // make the application wait until we press a key. System.in.read(); ((Lifecycle) engine).stop(); } catch (Exception e) { e.printStackTrace(); } }
@Override public List<String> setWsContainer(final HttpListener httpListener, final ClassLoader classLoader, String contextRoot, String virtualHost, final ServletInfo servletInfo, final String realmName, final String transportGuarantee, final String authMethod, final String moduleId) throws Exception { if (virtualHost == null) { virtualHost = engine.getDefaultHost(); } final Container host = engine.findChild(virtualHost); if (host == null) { throw new IllegalArgumentException("Invalid virtual host '" + virtualHost + "'. Do you have a matchiing Host entry in the server.xml?"); } if ("ROOT".equals(contextRoot)) { // doesn't happen in tomee itself but with all our tooling around contextRoot = ""; } if (!contextRoot.startsWith("/") && !contextRoot.isEmpty()) { contextRoot = "/" + contextRoot; } final Context context = (Context) host.findChild(contextRoot); if (context == null) { throw new IllegalArgumentException("Could not find web application context " + contextRoot + " in host " + host.getName()); } final Wrapper wrapper = (Wrapper) context.findChild(servletInfo.servletName); if (wrapper == null) { throw new IllegalArgumentException("Could not find servlet " + servletInfo.servletName + " in web application context " + context.getName()); } // for Pojo web services, we need to change the servlet class which is the service implementation // by the WsServler class wrapper.setServletClass(WsServlet.class.getName()); if (wrapper.getServlet() != null) { wrapper.unload(); // deallocate previous one wrapper.load(); // reload this one withuot unloading it to keep the instance - unload is called during stop() // boolean controlling this method call can't be set to false through API so let do it ourself wrapper.getServlet().init(StandardWrapper.class.cast(wrapper)); // or Reflections.set(wrapper, "instanceInitialized", false); } setWsContainer(context, wrapper, httpListener); // add service locations final List<String> addresses = new ArrayList<>(); for (final Connector connector : connectors) { for (final String mapping : wrapper.findMappings()) { final URI address = new URI(connector.getScheme(), null, host.getName(), connector.getPort(), (contextRoot.startsWith("/") ? "" : "/") + contextRoot + mapping, null, null); addresses.add(address.toString()); } } return addresses; }
/** * Equivalent with * <servlet><servlet-name><servlet-class>. * * In general it is better/faster to use the method that takes a * Servlet as param - this one can be used if the servlet is not * commonly used, and want to avoid loading all deps. * ( for example: jsp servlet ) * * You can customize the returned servlet, ex: * * wrapper.addInitParameter("name", "value"); */ public StandardWrapper addServlet(StandardContext ctx, String servletName, String servletClass) { // will do class for name and set init params StandardWrapper sw = (StandardWrapper)ctx.createWrapper(); sw.setServletClass(servletClass); sw.setName(servletName); ctx.addChild(sw); return sw; }