Thomas Herzog created OWB-803:
---------------------------------

             Summary: Forever loop when abstract decorator does not implement 
invoked method
                 Key: OWB-803
                 URL: https://issues.apache.org/jira/browse/OWB-803
             Project: OpenWebBeans
          Issue Type: Bug
          Components: Interceptor and Decorators
    Affects Versions: 1.1.7
            Reporter: Thomas Herzog
             Fix For: 1.1.8


If there is a decorated service, where the decorator is abstract and does not 
implement all methods of the interface,
then there will occur a forever loop within the 
org.apache.webbeans.decorator.DelegateHandler#invoke(Object instance, Method 
method, Object[] arguments) (line: 89),
if a method, which is not implemented in the abstract decorator, is tried to be 
invoked on the proxied decorator instance.

This occured within the openEjb-Lite 4.5.1 which uses openwebbeans 1.1.7.
As we have seen, owb 1.1.6 did implement it differently, so we switched back to 
OpebEjb-lite 4.5.0 which uses openwebbeans 1.1.6

{code:title="org.apache.webbeans.decorator.DelegateHandler#invoke(Object 
instance, Method method, Object[] arguments) openwebbeans 1.1.7"}
 public Object invoke(Object instance, Method method, Object[] arguments) 
throws Exception
    {
        // Tuck away a reference to the bean being Decorated
        if (actualInstance == null)
        {
            actualInstance = instance;
        }

        int hit = 0;
        int decoratorsSize = decorators.size();
        while (position.get().intValue() < decoratorsSize)
        {
            hit++;

            // !!!!!! Current position will always be 1, this part is 
implemented differntly in 1.1.6  !!!!!!
            int currentPosition = position.get().intValue();
            Object decorator = decorators.get(position.get().getAndIncrement());
            try
            {
                Method decMethod = 
decorator.getClass().getMethod(method.getName(), method.getParameterTypes());
                boolean methodInInterface = 
checkForMethodInInterfaces(decorator.getClass(), method);

                if (decMethod != null && methodInInterface)
                {
                    if (!decMethod.isAccessible())
                    {
                        
bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(decMethod,
 true);
                    }

                    try
                    {
                        return decMethod.invoke(decorator, arguments);
                    }
                    finally
                    {
                        if (currentPosition == 0) // if we go back on the first 
decorator no more need of this thread local
                        {
                            position.remove();
                        }
                    }
                }

            }
            catch (SecurityException e)
            {
                logger.log(Level.SEVERE, OWBLogConst.ERROR_0011, 
WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
                throw new WebBeansException(e);

            }
            catch (NoSuchMethodException e)
            {
                continue;
            }
            catch (InvocationTargetException e)
            {
                Throwable cause = e.getCause();
                //If the wrapped exception tells us the method didn't exist, 
continue
                if(cause instanceof NoSuchMethodException)
                {
                    continue;
                }

                logger.log(Level.SEVERE, OWBLogConst.ERROR_0012, 
WebBeansLoggerFacade.args(e.getTargetException(), method.getName(), 
decorator.getClass().getName()));

                if (cause instanceof Exception)
                {
                    throw (Exception) cause;
                }
                else if (cause instanceof Error)
                {
                    throw (Error) cause;
                }
                else
                {
                    throw new WebBeansException(e);
                }
            }
            catch (IllegalAccessException e)
            {
                logger.log(Level.SEVERE, OWBLogConst.ERROR_0014, 
WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
                throw new WebBeansException(e);
            }

        }

        if (hit == decoratorsSize) // if we hit all decorators but noone was 
called (see while loop) then clean here
        {
            position.remove();
        }

        if (!method.isAccessible())
        {
            
bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(method,
 true);
        }

        Object result = null;
        
        if(!(bean instanceof EnterpriseBeanMarker))
        {
            result = method.invoke(actualInstance, arguments);
        }
        else
        {
            if(ejbContext != null)
            {
                Method ejbMethod = ejbContext.getMethod();
                
                // don't use method.equals(), it may only differ by being 
abstract in the EJB proxy.
                 
                if (method.getName().equals(ejbMethod.getName()) && 
                        
method.getReturnType().equals(ejbMethod.getReturnType())) 
                {
                    result = ejbContext.proceed();
                }

                else 
                {
                    Object ejbInstance = ejbContext.getTarget();
                    result = method.invoke(ejbInstance, arguments);
                }
            }
        }

        return result;

    }
{code}

{code:title="org.apache.webbeans.decorator.DelegateHandler#invoke(Object 
instance, Method method, Object[] arguments) openwebbeans 1.1.6"}
   public Object invoke(Object instance, Method method, Object[] arguments) 
throws Exception
    {
        // Tuck away a reference to the bean being Decorated
        if (actualInstance == null)
        {
            actualInstance = instance;
        }

        while (position.get().intValue() < decorators.size())
        {

                    // !!!! No current position occurs here !!!!!
                        // !!!! This works when not implemented method of 
abstract decorator is tried to be invoked !!!!!
            Object decorator = decorators.get(position.get().getAndIncrement());

            try
            {
                Method decMethod = 
decorator.getClass().getMethod(method.getName(), method.getParameterTypes());
                boolean methodInInterface = 
checkForMethodInInterfaces(decorator.getClass(), method);

                if (decMethod != null && methodInInterface)
                {
                    if (!decMethod.isAccessible())
                    {
                        
bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(decMethod,
 true);
                    }

                    Object returnValue = decMethod.invoke(decorator, arguments);
                    position.remove();
                    return returnValue;
                }

            }
            catch (SecurityException e)
            {
                logger.log(Level.SEVERE, OWBLogConst.ERROR_0011, 
WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
                throw new WebBeansException(e);

            }
            catch (NoSuchMethodException e)
            {
                continue;
            }
            catch (InvocationTargetException e)
            {
                Throwable cause = e.getCause();
                //If the wrapped exception tells us the method didn't exist, 
continue
                if(cause instanceof NoSuchMethodException)
                {
                    continue;
                }

                logger.log(Level.SEVERE, OWBLogConst.ERROR_0012, 
WebBeansLoggerFacade.args(e.getTargetException(), method.getName(), 
decorator.getClass().getName()));

                if (cause instanceof Exception)
                {
                    throw (Exception) cause;
                }
                else if (cause instanceof Error)
                {
                    throw (Error) cause;
                }
                else
                {
                    throw new WebBeansException(e);
                }
            }
            catch (IllegalAccessException e)
            {
                logger.log(Level.SEVERE, OWBLogConst.ERROR_0014, 
WebBeansLoggerFacade.args(method.getName(), decorator.getClass().getName()));
                throw new WebBeansException(e);
            }

        }

        position.remove();

        if (!method.isAccessible())
        {
            
bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(method,
 true);
        }

        Object result = null;
        
        if(!(bean instanceof EnterpriseBeanMarker))
        {
            result = method.invoke(actualInstance, arguments);
        }
        else
        {
            if(ejbContext != null)
            {
                Method ejbMethod = ejbContext.getMethod();
                
                // don't use method.equals(), it may only differ by being 
abstract in the EJB proxy.
                 
                if (method.getName().equals(ejbMethod.getName()) && 
                        
method.getReturnType().equals(ejbMethod.getReturnType())) 
                {
                    result = ejbContext.proceed();
                }

                else 
                {
                    Object ejbInstance = ejbContext.getTarget();
                    result = method.invoke(ejbInstance, arguments);
                }
            }
        }
        
        return result;

    }
{code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to