You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by da...@apache.org on 2006/10/25 23:52:41 UTC

svn commit: r467775 - in /cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks: BlockCallStack.java BlockConnection.java BlockContext.java components/BlockPathModule.java components/BlockPropertyModule.java

Author: danielf
Date: Wed Oct 25 14:52:40 2006
New Revision: 467775

URL: http://svn.apache.org/viewvc?view=rev&rev=467775
Log:
Hopefully fixed the bug described in JIRA COCOON-1939 - Stack overflow when inheriting from block that alread inherits from another one.
The solution is the one that I proposed in the JIRA issue. Not much testing though.

Modified:
    cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockCallStack.java
    cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockConnection.java
    cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java
    cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPathModule.java
    cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPropertyModule.java

Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockCallStack.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockCallStack.java?view=diff&rev=467775&r1=467774&r2=467775
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockCallStack.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockCallStack.java Wed Oct 25 14:52:40 2006
@@ -31,6 +31,16 @@
 
     /** The block stack */
     private static final ThreadLocal blockStack = new ThreadLocal();
+    
+    /** Keep track on if it is an ordinary or a super call */
+    private static class BlockCallStackInfo {
+        public BlockCallStackInfo(ServletContext servletContext, boolean superCall) {
+            this.servletContext = servletContext;
+            this.superCall = superCall;
+        }
+        public ServletContext servletContext;
+        public boolean superCall;
+    };
 
     /**
      * This hook must be called each time a block is entered.
@@ -42,6 +52,24 @@
      */
     public static void enterBlock(ServletContext context)
     throws ServletException {
+        enterBlock(context, false);
+    }
+
+    /**
+     * This hook must be called each time a super block is entered.
+     *
+     * <p>This method should never raise an exception, except when the
+     * parameters are not set!</p>
+     *
+     * @throws ServletException if block is null
+     */
+    public static void enterSuperBlock(ServletContext context)
+    throws ServletException {
+        enterBlock(context, true);
+    }
+
+    private static void enterBlock(ServletContext context, boolean superCall)
+    throws ServletException {
         if (null == context) {
             throw new ServletException("Block is not set.");
         }
@@ -51,7 +79,8 @@
             stack = new Stack();
             blockStack.set(stack);
         }
-        stack.push(context);
+        BlockCallStackInfo info = new BlockCallStackInfo(context, superCall);
+        stack.push(info);
     }
 
     /**
@@ -65,10 +94,32 @@
         stack.pop();
     }
 
+    /**
+     * Use this method for getting the context that should be used for
+     * resolving a polymorphic block protocol call 
+     * @return a servlet context
+     */
+    public static ServletContext getBaseBlockContext() {
+        final Stack stack = (Stack)blockStack.get();
+        if (stack != null) {
+            for(int i = stack.size() - 1; i >= 0; i--) {
+                BlockCallStackInfo info = (BlockCallStackInfo) stack.elementAt(i);
+                if (!info.superCall)
+                    return info.servletContext;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Use this method for getting the context that should be used for
+     * resolving a block protocol call to a super block 
+     * @return a servlet context
+     */
     public static ServletContext getCurrentBlockContext() {
         final Stack stack = (Stack)blockStack.get();
         if (stack != null && !stack.isEmpty()) {
-                return (ServletContext)stack.peek();
+            return ((BlockCallStackInfo)stack.peek()).servletContext;
         }
         return null;
     }

Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockConnection.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockConnection.java?view=diff&rev=467775&r1=467774&r2=467775
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockConnection.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockConnection.java Wed Oct 25 14:52:40 2006
@@ -68,10 +68,6 @@
 
         this.logger = logger;
         
-        this.context = BlockCallStack.getCurrentBlockContext();
-        if (this.context == null)
-            throw new MalformedURLException("Must be used in a block context " + url);
-
         URI blockURI = null;
         try {
             blockURI = parseBlockURI(new URI(url.toString()));
@@ -79,6 +75,16 @@
             throw new MalformedURLException("Malformed URI in block source " +
                                             e.getMessage());
         }
+
+        // Super calls are resolved relative the current context and ordinary
+        // calls relative the last non super call in the call chain
+        if (BlockContext.SUPER.equals(this.blockName))
+            this.context = BlockCallStack.getCurrentBlockContext();
+        else
+            this.context = BlockCallStack.getBaseBlockContext();
+        
+        if (this.context == null)
+            throw new MalformedURLException("Must be used in a block context " + url);
 
         this.request = new BlockCallHttpServletRequest(blockURI);
         this.response = new BlockCallHttpServletResponse();

Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java?view=diff&rev=467775&r1=467774&r2=467775
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/BlockContext.java Wed Oct 25 14:52:40 2006
@@ -378,22 +378,22 @@
             RequestDispatcher dispatcher =
                 this.context.getRequestDispatcher(((HttpServletRequest)request).getPathInfo());
             if (dispatcher != null) {
-                if (!this.superCall) {
-                    try {
+                try {
+                    if (!this.superCall) {
                         // It is important to set the current block each time
                         // a new block is entered, this is used for the block
                         // protocol
                         BlockCallStack.enterBlock(this.context);
-                        dispatcher.forward(request, response);
-                    } finally {
-                        BlockCallStack.leaveBlock();
-                    }
-                } else {
-                    // A super block should be called in the context of
-                    // the called block to get polymorphic calls resolved
-                    // in the right way. Therefore no new current block is
-                    // set.
+                    } else {
+                        // A super block should be called in the context of
+                        // the called block to get polymorphic calls resolved
+                        // in the right way. We still need to register the
+                        // current context for resolving super calls relative it.
+                        BlockCallStack.enterSuperBlock(this.context);
+                    }                        
                     dispatcher.forward(request, response);
+                } finally {
+                    BlockCallStack.leaveBlock();
                 }
             } else {
                 // Cannot happen

Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPathModule.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPathModule.java?view=diff&rev=467775&r1=467774&r2=467775
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPathModule.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPathModule.java Wed Oct 25 14:52:40 2006
@@ -41,7 +41,7 @@
     public Object getAttribute( String name, Configuration modeConf, Map objectModel )
     throws ConfigurationException {
         Environment env = EnvironmentHelper.getCurrentEnvironment();
-        BlockContext blockContext = (BlockContext) BlockCallStack.getCurrentBlockContext();
+        BlockContext blockContext = (BlockContext) BlockCallStack.getBaseBlockContext();
         String absoluteURI = null;
         /* No relative block paths yet
         String baseURI = env.getURIPrefix();

Modified: cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPropertyModule.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPropertyModule.java?view=diff&rev=467775&r1=467774&r2=467775
==============================================================================
--- cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPropertyModule.java (original)
+++ cocoon/trunk/core/cocoon-blocks-fw/cocoon-blocks-fw-impl/src/main/java/org/apache/cocoon/blocks/components/BlockPropertyModule.java Wed Oct 25 14:52:40 2006
@@ -35,7 +35,7 @@
 
     public Object getAttribute( String name, Configuration modeConf, Map objectModel )
     throws ConfigurationException {
-        return BlockCallStack.getCurrentBlockContext().getInitParameter(name);
+        return BlockCallStack.getBaseBlockContext().getInitParameter(name);
     }
 
     public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)