public void compileExpression()

in tapestry-framework/src/org/apache/tapestry/enhance/javassist/OGNLExpressionCompiler.java [128:236]


    public void compileExpression(OgnlContext context, Node expression, Object root)
            throws Exception
    {
        if (_log.isDebugEnabled())
            _log.debug("Compiling expr class " + expression.getClass().getName()
                       + " and root " + root.getClass().getName() + " with toString:" + expression.toString());

        synchronized (expression)
        {
            if (expression.getAccessor() != null)
                return;

            String getBody = null;
            String setBody;

            MethodSignature valueGetter = new MethodSignatureImpl(Object.class, "get", new Class[]{OgnlContext.class, Object.class}, null);
            MethodSignature valueSetter = new MethodSignatureImpl(void.class, "set", new Class[]{OgnlContext.class, Object.class, Object.class}, null);

            CompiledExpression compiled = new CompiledExpression(expression, root, valueGetter, valueSetter);

            MethodSignature expressionSetter = new MethodSignatureImpl(void.class, "setExpression", new Class[]{Node.class}, null);

            try
            {
                getBody = generateGetter(context, compiled);
            } catch (UnsupportedCompilationException uc)
            {
                // uc.printStackTrace();
                // The target object may not fully resolve yet because of a partial tree with a null somewhere, we
                // don't want to bail out forever because it might be enhancable on another pass eventually
                return;
            } catch (javassist.CannotCompileException e)
            {
                _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, e);

                e.printStackTrace();

                generateFailSafe(context, expression, root);
                return;
            }

            try
            {
                generateClassFab(compiled).addMethod(Modifier.PUBLIC, valueGetter, getBody);
            } catch (Throwable t)
            {
                _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, t);

                t.printStackTrace();

                generateFailSafe(context, expression, root);
                return;
            }

            try
            {
                setBody = generateSetter(context, compiled);
            } catch (UnsupportedCompilationException uc)
            {
                //_log.warn("Unsupported setter compilation caught: " + uc.getMessage() + " for expression: " + expression.toString(), uc);

                setBody = generateOgnlSetter(generateClassFab(compiled), valueSetter);

                if (!generateClassFab(compiled).containsMethod(expressionSetter))
                {
                    generateClassFab(compiled).addField("_node", Node.class);
                    generateClassFab(compiled).addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
                }
            }

            try
            {
                if (setBody == null)
                {
                    setBody = generateOgnlSetter(generateClassFab(compiled), valueSetter);

                    if (!generateClassFab(compiled).containsMethod(expressionSetter))
                    {
                        generateClassFab(compiled).addField("_node", Node.class);
                        generateClassFab(compiled).addMethod(Modifier.PUBLIC, expressionSetter, "{ _node = $1; }");
                    }
                }

                if (setBody != null)
                    generateClassFab(compiled).addMethod(Modifier.PUBLIC, valueSetter, setBody);

                generateClassFab(compiled).addConstructor(new Class[0], new Class[0], "{}");

                Class clazz = generateClassFab(compiled).createEnhancedSubclass();

                expression.setAccessor((ExpressionAccessor) clazz.newInstance());

            }  catch (Throwable t)
            {
                _log.error("Error generating OGNL statements for expression " + expression + " with root " + root, t);
                t.printStackTrace();

                generateFailSafe(context, expression, root);
                return;
            }

            // need to set expression on node if the field was just defined.

            if (generateClassFab(compiled).containsMethod(expressionSetter))
            {
                expression.getAccessor().setExpression(expression);
            }
        }
    }