Author: markt Date: Fri Oct 28 14:14:22 2011 New Revision: 1190339 URL: http://svn.apache.org/viewvc?rev=1190339&view=rev Log: Merge branch 'bug51744' into trunk
Modified: tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java tomcat/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/trunk/java/org/apache/naming/NamingContext.java tomcat/trunk/test/org/apache/naming/resources/TestNamingContext.java tomcat/trunk/webapps/docs/config/context.xml Modified: tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java?rev=1190339&r1=1190338&r2=1190339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/NamingContextListener.java Fri Oct 28 14:14:22 2011 @@ -141,6 +141,13 @@ public class NamingContextListener /** + * Determines if an attempt to write to a read-only context results in an + * exception or if the request is ignored. + */ + private boolean exceptionOnFailedWrite = true; + + + /** * The string manager for this package. */ protected static final StringManager sm = @@ -149,6 +156,25 @@ public class NamingContextListener // ------------------------------------------------------------- Properties + /** + * Returns whether or not an attempt to modify the JNDI context will trigger + * an exception or if the request will be ignored. + */ + public boolean getExceptionOnFailedWrite() { + return exceptionOnFailedWrite; + } + + + /** + * Controls whether or not an attempt to modify the JNDI context will + * trigger an exception or if the request will be ignored. + * + * @param exceptionOnFailedWrite The new value + */ + public void setExceptionOnFailedWrite(boolean exceptionOnFailedWrite) { + this.exceptionOnFailedWrite = exceptionOnFailedWrite; + } + /** * Return the "name" property. @@ -214,6 +240,10 @@ public class NamingContextListener log.debug("Bound " + container ); } + // Configure write when read-only behaviour + namingContext.setExceptionOnFailedWrite( + getExceptionOnFailedWrite()); + // Setting the context in read/write mode ContextAccessController.setWritable(getName(), container); Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1190339&r1=1190338&r2=1190339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Fri Oct 28 14:14:22 2011 @@ -834,6 +834,7 @@ public class StandardContext extends Con private boolean sendRedirectBody = false; + private boolean jndiExceptionOnFailedWrite = true; // ----------------------------------------------------- Context Properties @@ -2429,6 +2430,26 @@ public class StandardContext extends Con // ------------------------------------------------------ Public Properties + /** + * Returns whether or not an attempt to modify the JNDI context will trigger + * an exception or if the request will be ignored. + */ + public boolean getJndiExceptionOnFailedWrite() { + return jndiExceptionOnFailedWrite; + } + + + /** + * Controls whether or not an attempt to modify the JNDI context will + * trigger an exception or if the request will be ignored. + * + * @param jndiExceptionOnFailedWrite + */ + public void setJndiExceptionOnFailedWrite( + boolean jndiExceptionOnFailedWrite) { + this.jndiExceptionOnFailedWrite = jndiExceptionOnFailedWrite; + } + /** * Return the Locale to character set mapper class for this Context. @@ -4969,6 +4990,7 @@ public class StandardContext extends Con if (getNamingContextListener() == null) { NamingContextListener ncl = new NamingContextListener(); ncl.setName(getNamingContextName()); + ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite()); addLifecycleListener(ncl); setNamingContextListener(ncl); } Modified: tomcat/trunk/java/org/apache/naming/NamingContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/NamingContext.java?rev=1190339&r1=1190338&r2=1190339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/NamingContext.java (original) +++ tomcat/trunk/java/org/apache/naming/NamingContext.java Fri Oct 28 14:14:22 2011 @@ -123,12 +123,21 @@ public class NamingContext implements Co protected String name; - // --------------------------------------------------------- Public Methods + /** + * Determines if an attempt to write to a read-only context results in an + * exception or if the request is ignored. + */ + private boolean exceptionOnFailedWrite = true; + public boolean getExceptionOnFailedWrite() { + return exceptionOnFailedWrite; + } + public void setExceptionOnFailedWrite(boolean exceptionOnFailedWrite) { + this.exceptionOnFailedWrite = exceptionOnFailedWrite; + } // -------------------------------------------------------- Context Methods - /** * Retrieves the named object. If name is empty, returns a new instance * of this context (which represents the same naming context as this @@ -249,9 +258,11 @@ public class NamingContext implements Co * @exception NamingException if a naming exception is encountered */ @Override - public void unbind(Name name) - throws NamingException { - checkWritable(); + public void unbind(Name name) throws NamingException { + + if (!checkWritable()) { + return; + } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); @@ -465,10 +476,11 @@ public class NamingContext implements Co * a context, or does not name a context of the appropriate type */ @Override - public void destroySubcontext(Name name) - throws NamingException { + public void destroySubcontext(Name name) throws NamingException { - checkWritable(); + if (!checkWritable()) { + return; + } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); @@ -533,13 +545,16 @@ public class NamingContext implements Co * @exception NamingException if a naming exception is encountered */ @Override - public Context createSubcontext(Name name) - throws NamingException { - checkWritable(); + public Context createSubcontext(Name name) throws NamingException { + if (!checkWritable()) { + return null; + } - Context newContext = new NamingContext(env, this.name); + NamingContext newContext = new NamingContext(env, this.name); bind(name, newContext); + newContext.setExceptionOnFailedWrite(getExceptionOnFailedWrite()); + return newContext; } @@ -744,7 +759,9 @@ public class NamingContext implements Co */ @Override public void close() throws NamingException { - checkWritable(); + if (!checkWritable()) { + return; + } env.clear(); } @@ -866,7 +883,9 @@ public class NamingContext implements Co protected void bind(Name name, Object obj, boolean rebind) throws NamingException { - checkWritable(); + if (!checkWritable()) { + return; + } while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1); @@ -935,12 +954,16 @@ public class NamingContext implements Co /** * Throws a naming exception is Context is not writable. */ - protected void checkWritable() - throws NamingException { - if (!isWritable()) - throw new NamingException(sm.getString("namingContext.readOnly")); + protected boolean checkWritable() throws NamingException { + if (isWritable()) { + return true; + } else { + if (exceptionOnFailedWrite) { + throw new javax.naming.OperationNotSupportedException( + sm.getString("namingContext.readOnly")); + } + } + return false; } - - } Modified: tomcat/trunk/test/org/apache/naming/resources/TestNamingContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/naming/resources/TestNamingContext.java?rev=1190339&r1=1190338&r2=1190339&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/naming/resources/TestNamingContext.java (original) +++ tomcat/trunk/test/org/apache/naming/resources/TestNamingContext.java Fri Oct 28 14:14:22 2011 @@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletReq import javax.servlet.http.HttpServletResponse; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -215,7 +216,17 @@ public class TestNamingContext extends T } @Test - public void testBug51744() throws Exception { + public void testBug51744a() throws Exception { + doTestBug51744(true); + } + + @Test + public void testBug51744b() throws Exception { + doTestBug51744(false); + } + + private void doTestBug51744(boolean exceptionOnFailedWrite) + throws Exception { Tomcat tomcat = getTomcatInstance(); tomcat.enableNaming(); @@ -223,6 +234,8 @@ public class TestNamingContext extends T StandardContext ctx = (StandardContext) tomcat.addContext("", System.getProperty("java.io.tmpdir")); + ctx.setJndiExceptionOnFailedWrite(exceptionOnFailedWrite); + // Map the test Servlet Bug51744Servlet bug51744Servlet = new Bug51744Servlet(); Tomcat.addServlet(ctx, "bug51744Servlet", bug51744Servlet); @@ -233,7 +246,10 @@ public class TestNamingContext extends T ByteChunk bc = new ByteChunk(); int rc = getUrl("http://localhost:" + getPort() + "/", bc, null); assertEquals(200, rc); - assertEquals(Bug51744Servlet.EXPECTED, bc.toString()); + assertTrue(bc.toString().contains(Bug51744Servlet.EXPECTED)); + if (exceptionOnFailedWrite) { + assertTrue(bc.toString().contains(Bug51744Servlet.ERROR_MESSAGE)); + } } public static final class Bug51744Servlet extends HttpServlet { @@ -241,6 +257,7 @@ public class TestNamingContext extends T private static final long serialVersionUID = 1L; public static final String EXPECTED = "TestValue"; + public static final String ERROR_MESSAGE = "Error"; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) @@ -254,18 +271,13 @@ public class TestNamingContext extends T Context env1 = (Context) ctx1.lookup("java:comp/env"); env1.addToEnvironment("TestName", EXPECTED); - boolean error = false; + out.print(env1.getEnvironment().get("TestName")); + try { env1.close(); } catch (NamingException ne) { - error = true; + out.print(ERROR_MESSAGE); } - if (!error) { - throw new ServletException( - "No error when one was expected"); - } - - out.print(env1.getEnvironment().get("TestName")); } catch (NamingException ne) { ne.printStackTrace(out); } Modified: tomcat/trunk/webapps/docs/config/context.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1190339&r1=1190338&r2=1190339&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/context.xml (original) +++ tomcat/trunk/webapps/docs/config/context.xml Fri Oct 28 14:14:22 2011 @@ -657,6 +657,19 @@ not specified, the default value of <code>false</code> will be used.</p> </attribute> + <attribute name="jndiExceptionOnFailedWrite" required="false"> + <p>If <code>true</code>, any attempt by an application to modify the + provided JNDI context with a call to bind(), unbind(), + createSubContext(), destroySubContext() or close() will trigger a + <code>javax.naming.OperationNotSupportedException</code> as required by + section EE.5.3.4 of the Java EE specification. This exception can be + disabled by setting this attribute to true in which case any calls to + modify the JNDI context will return <b>without</b> making any changes + and methods that return values will return <code>null</code>. If not + specified, the specification compliant default of <code>true</code> will + be used.</p> + </attribute> + <attribute name="processTlds" required="false"> <p>Whether the context should process TLDs on startup. The default is true. The false setting is intended for special cases --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org