/** * Return the URL to the resource that is mapped to a specified path. The path must begin with a * "/" and is interpreted as relative to the current context root. * * @param path The path to the desired resource * @exception MalformedURLException if the path is not given in the correct form */ public URL getResource(String path) throws MalformedURLException { DirContext resources = context.getResources(); if (resources != null) { String fullPath = context.getName() + path; // this is the problem. Host must not be null String hostName = context.getParent().getName(); try { resources.lookup(path); if (System.getSecurityManager() != null) { try { PrivilegedGetResource dp = new PrivilegedGetResource(hostName, fullPath, resources); return (URL) AccessController.doPrivileged(dp); } catch (PrivilegedActionException pe) { throw pe.getException(); } } else { return new URL( "jndi", null, 0, getJNDIUri(hostName, fullPath), new DirContextURLStreamHandler(resources)); } } catch (Exception e) { // e.printStackTrace(); } } return (null); }
@Test public void testFlagFailCtxIfServletStartFails() throws Exception { Tomcat tomcat = getTomcatInstance(); File docBase = new File(System.getProperty("java.io.tmpdir")); StandardContext context = (StandardContext) tomcat.addContext("", docBase.getAbsolutePath()); // first we test the flag itself, which can be set on the Host and // Context assertFalse(context.getComputedFailCtxIfServletStartFails()); StandardHost host = (StandardHost) tomcat.getHost(); host.setFailCtxIfServletStartFails(true); assertTrue(context.getComputedFailCtxIfServletStartFails()); context.setFailCtxIfServletStartFails(Boolean.FALSE); assertFalse( "flag on Context should override Host config", context.getComputedFailCtxIfServletStartFails()); // second, we test the actual effect of the flag on the startup Wrapper servlet = Tomcat.addServlet(context, "myservlet", new FailingStartupServlet()); servlet.setLoadOnStartup(1); tomcat.start(); assertTrue("flag false should not fail deployment", context.getState().isAvailable()); tomcat.stop(); assertFalse(context.getState().isAvailable()); host.removeChild(context); context = (StandardContext) tomcat.addContext("", docBase.getAbsolutePath()); servlet = Tomcat.addServlet(context, "myservlet", new FailingStartupServlet()); servlet.setLoadOnStartup(1); tomcat.start(); assertFalse("flag true should fail deployment", context.getState().isAvailable()); }
/** * Bind the specified value with the specified context attribute name, replacing any existing * value for that name. * * @param name Attribute name to be bound * @param value New attribute value to be bound */ public void setAttribute(String name, Object value) { // Name cannot be null if (name == null) throw new IllegalArgumentException(sm.getString("applicationContext.setAttribute.namenull")); // Null value is the same as removeAttribute() if (value == null) { removeAttribute(name); return; } Object oldValue = null; boolean replaced = false; // Add or replace the specified attribute synchronized (attributes) { // Check for read only attribute if (readOnlyAttributes.containsKey(name)) return; oldValue = attributes.get(name); if (oldValue != null) replaced = true; attributes.put(name, value); } // Notify interested application event listeners Object listeners[] = context.getApplicationListeners(); if ((listeners == null) || (listeners.length == 0)) return; ServletContextAttributeEvent event = null; if (replaced) event = new ServletContextAttributeEvent(context.getServletContext(), name, oldValue); else event = new ServletContextAttributeEvent(context.getServletContext(), name, value); for (int i = 0; i < listeners.length; i++) { if (!(listeners[i] instanceof ServletContextAttributeListener)) continue; ServletContextAttributeListener listener = (ServletContextAttributeListener) listeners[i]; try { if (replaced) { context.fireContainerEvent("beforeContextAttributeReplaced", listener); listener.attributeReplaced(event); context.fireContainerEvent("afterContextAttributeReplaced", listener); } else { context.fireContainerEvent("beforeContextAttributeAdded", listener); listener.attributeAdded(event); context.fireContainerEvent("afterContextAttributeAdded", listener); } } catch (Throwable t) { if (replaced) context.fireContainerEvent("afterContextAttributeReplaced", listener); else context.fireContainerEvent("afterContextAttributeAdded", listener); // FIXME - should we do anything besides log these? log(sm.getString("applicationContext.attributeEvent"), t); } } }
/** * Return a <code>RequestDispatcher</code> instance that acts as a wrapper for the resource at the * given path. The path must begin with a "/" and is interpreted as relative to the current * context root. * * @param path The path to the desired resource. */ public RequestDispatcher getRequestDispatcher(String path) { // Validate the path argument if (path == null) return (null); if (!path.startsWith("/")) throw new IllegalArgumentException( sm.getString("applicationContext.requestDispatcher.iae", path)); if (normalize(path) == null) return (null); // Construct a "fake" request to be mapped by our Context String contextPath = context.getPath(); if (contextPath == null) contextPath = ""; String relativeURI = path; String queryString = null; int question = path.indexOf('?'); if (question >= 0) { relativeURI = path.substring(0, question); queryString = path.substring(question + 1); } if (System.getSecurityManager() != null) { PrivilegedGetRequestDispatcher dp = new PrivilegedGetRequestDispatcher(contextPath, relativeURI, queryString); return (RequestDispatcher) AccessController.doPrivileged(dp); } // The remaining code is duplicated in PrivilegedGetRequestDispatcher, // we need to make sure they stay in sync HttpRequest request = new MappingRequest(context.getPath(), contextPath + relativeURI, queryString); /* request.setContext(context); request.setContextPath(context.getPath()); request.setRequestURI(contextPath + relativeURI); request.setQueryString(queryString); */ Wrapper wrapper = (Wrapper) context.map(request, true); if (wrapper == null) return (null); // Construct a RequestDispatcher to process this request HttpServletRequest hrequest = (HttpServletRequest) request.getRequest(); return (RequestDispatcher) new ApplicationDispatcher( wrapper, hrequest.getServletPath(), hrequest.getPathInfo(), hrequest.getQueryString(), null); }
/** * Return the real path for a given virtual path, if possible; otherwise return <code>null</code>. * * @param path The path to the desired resource */ public String getRealPath(String path) { if (!context.isFilesystemBased()) return null; File file = new File(basePath, path); return (file.getAbsolutePath()); }
/** Release the Filter instance associated with this FilterConfig, if there is one. */ void release() { unregisterJMX(); if (this.filter != null) { if (Globals.IS_SECURITY_ENABLED) { try { SecurityUtil.doAsPrivilege("destroy", filter); } catch (java.lang.Exception ex) { context.getLogger().error("ApplicationFilterConfig.doAsPrivilege", ex); } SecurityUtil.remove(filter); } else { filter.destroy(); } if (!context.getIgnoreAnnotations()) { try { ((StandardContext) context).getInstanceManager().destroyInstance(this.filter); } catch (Exception e) { Throwable t = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(t); context.getLogger().error("ApplicationFilterConfig.preDestroy", t); } } } this.filter = null; }
/** * Merge the context initialization parameters specified in the application deployment descriptor * with the application parameters described in the server configuration, respecting the <code> * override</code> property of the application parameters appropriately. */ private void mergeParameters() { if (parameters != null) return; HashMap results = new HashMap(); String names[] = context.findParameters(); for (int i = 0; i < names.length; i++) results.put(names[i], context.findParameter(names[i])); ApplicationParameter params[] = context.findApplicationParameters(); for (int i = 0; i < params.length; i++) { if (params[i].getOverride()) { if (results.get(params[i].getName()) == null) results.put(params[i].getName(), params[i].getValue()); } else { results.put(params[i].getName(), params[i].getValue()); } } parameters = results; }
/** * Return the MIME type of the specified file, or <code>null</code> if the MIME type cannot be * determined. * * @param file Filename for which to identify a MIME type */ public String getMimeType(String file) { if (file == null) return (null); int period = file.lastIndexOf("."); if (period < 0) return (null); String extension = file.substring(period + 1); if (extension.length() < 1) return (null); return (context.findMimeMapping(extension)); }
private void registerJMX() { String parentName = context.getName(); if (!parentName.startsWith("/")) { parentName = "/" + parentName; } String hostName = context.getParent().getName(); hostName = (hostName == null) ? "DEFAULT" : hostName; // domain == engine name String domain = context.getParent().getParent().getName(); String webMod = "//" + hostName + parentName; String onameStr = null; String filterName = filterDef.getFilterName(); if (Util.objectNameValueNeedsQuote(filterName)) { filterName = ObjectName.quote(filterName); } if (context instanceof StandardContext) { StandardContext standardContext = (StandardContext) context; onameStr = domain + ":j2eeType=Filter,WebModule=" + webMod + ",name=" + filterName + ",J2EEApplication=" + standardContext.getJ2EEApplication() + ",J2EEServer=" + standardContext.getJ2EEServer(); } else { onameStr = domain + ":j2eeType=Filter,name=" + filterName + ",WebModule=" + webMod; } try { oname = new ObjectName(onameStr); Registry.getRegistry(null, null).registerComponent(this, oname, null); } catch (Exception ex) { log.info( sm.getString( "applicationFilterConfig.jmxRegisterFail", getFilterClass(), getFilterName()), ex); } }
/** * Return a <code>RequestDispatcher</code> object that acts as a wrapper for the named servlet. * * @param name Name of the servlet for which a dispatcher is requested */ public RequestDispatcher getNamedDispatcher(String name) { // Validate the name argument if (name == null) return (null); // Create and return a corresponding request dispatcher Wrapper wrapper = (Wrapper) context.findChild(name); if (wrapper == null) return (null); ApplicationDispatcher dispatcher = new ApplicationDispatcher(wrapper, null, null, null, name); return ((RequestDispatcher) dispatcher); }
/** * Return the requested resource as an <code>InputStream</code>. The path must be specified * according to the rules described under <code>getResource</code>. If no such resource can be * identified, return <code>null</code>. * * @param path The path to the desired resource. */ public InputStream getResourceAsStream(String path) { DirContext resources = context.getResources(); if (resources != null) { try { Object resource = resources.lookup(path); if (resource instanceof Resource) return (((Resource) resource).streamContent()); } catch (Exception e) { } } return (null); }
/** * Return a Set containing the resource paths of resources member of the specified collection. * Each path will be a String starting with a "/" character. The returned set is immutable. * * @param path Collection path */ public Set getResourcePaths(String path) { DirContext resources = context.getResources(); if (resources != null) { if (System.getSecurityManager() != null) { PrivilegedAction dp = new PrivilegedGetResourcePaths(resources, path); return ((Set) AccessController.doPrivileged(dp)); } else { return (getResourcePathsInternal(resources, path)); } } return (null); }
/** * Return a <code>ServletContext</code> object that corresponds to a specified URI on the server. * This method allows servlets to gain access to the context for various parts of the server, and * as needed obtain <code>RequestDispatcher</code> objects or resources from the context. The * given path must be absolute (beginning with a "/"), and is interpreted based on our virtual * host's document root. * * @param uri Absolute URI of a resource on the server */ public ServletContext getContext(String uri) { // Validate the format of the specified argument if ((uri == null) || (!uri.startsWith("/"))) return (null); // Return the current context if requested String contextPath = context.getPath(); if (!contextPath.endsWith("/")) contextPath = contextPath + "/"; if ((contextPath.length() > 0) && (uri.startsWith(contextPath))) { return (this); } // Return other contexts only if allowed if (!context.getCrossContext()) return (null); try { Host host = (Host) context.getParent(); Context child = host.map(uri); if (child != null) return (child.getServletContext()); else return (null); } catch (Throwable t) { return (null); } }
/** * Remove the context attribute with the specified name, if any. * * @param name Name of the context attribute to be removed */ public void removeAttribute(String name) { Object value = null; boolean found = false; // Remove the specified attribute synchronized (attributes) { // Check for read only attribute if (readOnlyAttributes.containsKey(name)) return; found = attributes.containsKey(name); if (found) { value = attributes.get(name); attributes.remove(name); } else { return; } } // Notify interested application event listeners Object listeners[] = context.getApplicationListeners(); if ((listeners == null) || (listeners.length == 0)) return; ServletContextAttributeEvent event = new ServletContextAttributeEvent(context.getServletContext(), name, value); for (int i = 0; i < listeners.length; i++) { if (!(listeners[i] instanceof ServletContextAttributeListener)) continue; ServletContextAttributeListener listener = (ServletContextAttributeListener) listeners[i]; try { context.fireContainerEvent("beforeContextAttributeRemoved", listener); listener.attributeRemoved(event); context.fireContainerEvent("afterContextAttributeRemoved", listener); } catch (Throwable t) { context.fireContainerEvent("afterContextAttributeRemoved", listener); // FIXME - should we do anything besides log these? log(sm.getString("applicationContext.attributeEvent"), t); } } }
@Test public void testBug51653b() throws Exception { // Set up a container Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext("", null); // Traces order of events across multiple components StringBuilder trace = new StringBuilder(); // Add the page that generates the error Tomcat.addServlet(ctx, "test", new Bug51653ErrorTrigger()); ctx.addServletMapping("/test", "test"); // Add the error page Tomcat.addServlet(ctx, "errorPage", new Bug51653ErrorPage(trace)); ctx.addServletMapping("/error", "errorPage"); // And the handling for 404 responses ErrorPage errorPage = new ErrorPage(); errorPage.setErrorCode(Response.SC_NOT_FOUND); errorPage.setLocation("/error"); ctx.addErrorPage(errorPage); // Add the request listener Bug51653RequestListener reqListener = new Bug51653RequestListener(trace); ((StandardContext) ctx).addApplicationEventListener(reqListener); tomcat.start(); // Request a page that does not exist int rc = getUrl("http://localhost:" + getPort() + "/test", new ByteChunk(), null); // Need to allow time (but not too long in case the test fails) for // ServletRequestListener to complete int i = 20; while (i > 0) { if (trace.toString().endsWith("Destroy")) { break; } Thread.sleep(250); i--; } assertEquals(Response.SC_NOT_FOUND, rc); assertEquals("InitErrorDestroy", trace.toString()); }
@Test public void testSRLAfterError() throws Exception { // Set up a container Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext("", null); // Add the error page Tomcat.addServlet(ctx, "error", new ErrorServlet()); ctx.addServletMapping("/error", "error"); final List<String> result = new ArrayList<>(); // Add the request listener ServletRequestListener servletRequestListener = new ServletRequestListener() { @Override public void requestDestroyed(ServletRequestEvent sre) { result.add("Visit requestDestroyed"); } @Override public void requestInitialized(ServletRequestEvent sre) { result.add("Visit requestInitialized"); } }; ((StandardContext) ctx).addApplicationEventListener(servletRequestListener); tomcat.start(); // Request a page that triggers an error ByteChunk bc = new ByteChunk(); int rc = getUrl("http://localhost:" + getPort() + "/error?errorCode=400", bc, null); Assert.assertEquals(400, rc); Assert.assertTrue(result.contains("Visit requestInitialized")); Assert.assertTrue(result.contains("Visit requestDestroyed")); }
/** * Set the filter definition we are configured for. This has the side effect of instantiating an * instance of the corresponding filter class. * * @param filterDef The new filter definition * @exception ClassCastException if the specified class does not implement the <code> * javax.servlet.Filter</code> interface * @exception ClassNotFoundException if the filter class cannot be found * @exception IllegalAccessException if the filter class cannot be publicly instantiated * @exception InstantiationException if an exception occurs while instantiating the filter object * @exception ServletException if thrown by the filter's init() method * @throws NamingException * @throws InvocationTargetException */ void setFilterDef(FilterDef filterDef) throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException, InvocationTargetException, NamingException { this.filterDef = filterDef; if (filterDef == null) { // Release any previously allocated filter instance if (this.filter != null) { if (Globals.IS_SECURITY_ENABLED) { try { SecurityUtil.doAsPrivilege("destroy", filter); } catch (java.lang.Exception ex) { context.getLogger().error("ApplicationFilterConfig.doAsPrivilege", ex); } SecurityUtil.remove(filter); } else { filter.destroy(); } if (!context.getIgnoreAnnotations()) { try { ((StandardContext) context).getInstanceManager().destroyInstance(this.filter); } catch (Exception e) { Throwable t = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(t); context.getLogger().error("ApplicationFilterConfig.preDestroy", t); } } } this.filter = null; } else { // Allocate a new filter instance if necessary if (filterDef.getFilter() == null) { getFilter(); } } }
@Test(expected = IllegalArgumentException.class) public void testAddPreDestroyMethodConflicts() { StandardContext standardContext = new StandardContext(); standardContext.addPreDestroyMethod("a", "a"); standardContext.addPreDestroyMethod("a", "b"); }
private void testSetPath(String value, String expectedValue) { StandardContext context = new StandardContext(); context.setPath(value); Assert.assertEquals(expectedValue, context.getPath()); }
/** * Return the resources object that is mapped to a specified path. The path must begin with a "/" * and is interpreted as relative to the current context root. */ public DirContext getResources() { return context.getResources(); }
/** Return the display name of this web application. */ public String getServletContextName() { return (context.getDisplayName()); }
private void internalLog(Exception exception, String message) { Logger logger = context.getLogger(); if (logger != null) logger.log(exception, message); }
private void internalLog(String message, Throwable throwable) { Logger logger = context.getLogger(); if (logger != null) logger.log(message, throwable); }