EMMA Coverage Report (generated Tue May 18 22:13:27 CDT 2004)
[all classes][org.apache.velocity.runtime.parser.node]

COVERAGE SUMMARY FOR SOURCE FILE [ASTIdentifier.java]

nameclass, %method, %block, %line, %
ASTIdentifier.java100% (1/1)80%  (4/5)53%  (125/238)61%  (23.9/39)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ASTIdentifier100% (1/1)80%  (4/5)53%  (125/238)61%  (23.9/39)
ASTIdentifier (int): void 0%   (0/1)0%   (0/7)0%   (0/3)
execute (Object, InternalContextAdapter): Object 100% (1/1)46%  (89/195)56%  (16.3/29)
ASTIdentifier (Parser, int): void 100% (1/1)100% (8/8)100% (3/3)
init (InternalContextAdapter, Object): Object 100% (1/1)100% (23/23)100% (4/4)
jjtAccept (ParserVisitor, Object): Object 100% (1/1)100% (5/5)100% (1/1)

1package org.apache.velocity.runtime.parser.node;
2 
3/*
4 * Copyright 2000-2002,2004 The Apache Software Foundation.
5 * 
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * 
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 * 
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 
19import org.apache.velocity.context.InternalContextAdapter;
20import org.apache.velocity.runtime.parser.Parser;
21import org.apache.velocity.util.introspection.IntrospectionCacheData;
22import org.apache.velocity.util.introspection.Info;
23import org.apache.velocity.util.introspection.VelPropertyGet;
24 
25import org.apache.velocity.exception.MethodInvocationException;
26import org.apache.velocity.app.event.EventCartridge;
27 
28import java.lang.reflect.InvocationTargetException;
29 
30/**
31 *  ASTIdentifier.java
32 *
33 *  Method support for identifiers :  $foo
34 *
35 *  mainly used by ASTRefrence
36 *
37 *  Introspection is now moved to 'just in time' or at render / execution
38 *  time. There are many reasons why this has to be done, but the
39 *  primary two are   thread safety, to remove any context-derived
40 *  information from class member  variables.
41 *
42 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
43 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
44 * @version $Id: ASTIdentifier.java,v 1.19.4.1 2004/03/03 23:22:58 geirm Exp $
45 */
46public class ASTIdentifier extends SimpleNode
47{
48    private String identifier = "";
49 
50    /**
51     *  This is really immutable after the init, so keep one for this node
52     */
53    protected Info uberInfo;
54 
55    public ASTIdentifier(int id)
56    {
57        super(id);
58    }
59 
60    public ASTIdentifier(Parser p, int id)
61    {
62        super(p, id);
63    }
64 
65    /** Accept the visitor. **/
66    public Object jjtAccept(ParserVisitor visitor, Object data)
67    {
68        return visitor.visit(this, data);
69    }
70 
71    /**
72     *  simple init - don't do anything that is context specific.
73     *  just get what we need from the AST, which is static.
74     */
75    public  Object init(InternalContextAdapter context, Object data)
76        throws Exception
77    {
78        super.init(context, data);
79 
80        identifier = getFirstToken().image;
81 
82        uberInfo = new Info(context.getCurrentTemplateName(),
83                getLine(), getColumn());
84 
85        return data;
86    }
87 
88    /**
89     *  invokes the method on the object passed in
90     */
91    public Object execute(Object o, InternalContextAdapter context)
92        throws MethodInvocationException
93    {
94 
95        VelPropertyGet vg = null;
96 
97        try
98        {
99            Class c = o.getClass();
100 
101            /*
102             *  first, see if we have this information cached.
103             */
104 
105            IntrospectionCacheData icd = context.icacheGet(this);
106 
107            /*
108             * if we have the cache data and the class of the object we are
109             * invoked with is the same as that in the cache, then we must
110             * be allright.  The last 'variable' is the method name, and
111             * that is fixed in the template :)
112             */
113 
114            if (icd != null && icd.contextData == c)
115            {
116                vg = (VelPropertyGet) icd.thingy;
117            }
118            else
119            {
120                /*
121                 *  otherwise, do the introspection, and cache it.  Use the
122                 *  uberspector
123                 */
124 
125                vg = rsvc.getUberspect().getPropertyGet(o,identifier, uberInfo);
126 
127                if (vg != null && vg.isCacheable())
128                {
129                    icd = new IntrospectionCacheData();
130                    icd.contextData = c;
131                    icd.thingy = vg;
132                    context.icachePut(this,icd);
133                }
134            }
135        }
136        catch(Exception e)
137        {
138            rsvc.error("ASTIdentifier.execute() : identifier = "
139                               + identifier + " : " + e);
140        }
141 
142        /*
143         *  we have no getter... punt...
144         */
145 
146        if (vg == null)
147        {
148            return null;
149        }
150 
151        /*
152         *  now try and execute.  If we get a MIE, throw that
153         *  as the app wants to get these.  If not, log and punt.
154         */
155        try
156        {
157            return vg.invoke(o);
158        }
159        catch(InvocationTargetException ite)
160        {
161            EventCartridge ec = context.getEventCartridge();
162 
163            /*
164             *  if we have an event cartridge, see if it wants to veto
165             *  also, let non-Exception Throwables go...
166             */
167 
168            if (ec != null
169                    && ite.getTargetException() instanceof java.lang.Exception)
170            {
171                try
172                {
173                    return ec.methodException(o.getClass(), vg.getMethodName(),
174                            (Exception)ite.getTargetException());
175                }
176                catch(Exception e)
177                {
178                    throw new MethodInvocationException(
179                      "Invocation of method '" + vg.getMethodName() + "'"
180                      + " in  " + o.getClass()
181                      + " threw exception "
182                      + ite.getTargetException().getClass() + " : "
183                      + ite.getTargetException().getMessage(),
184                      ite.getTargetException(), vg.getMethodName());
185                }
186            }
187            else
188            {
189                /*
190                 * no event cartridge to override. Just throw
191                 */
192 
193                throw  new MethodInvocationException(
194                "Invocation of method '" + vg.getMethodName() + "'"
195                + " in  " + o.getClass()
196                + " threw exception "
197                + ite.getTargetException().getClass() + " : "
198                + ite.getTargetException().getMessage(),
199                ite.getTargetException(), vg.getMethodName());
200 
201 
202            }
203        }
204        catch(IllegalArgumentException iae)
205        {
206            return null;
207        }
208        catch(Exception e)
209        {
210            rsvc.error("ASTIdentifier() : exception invoking method "
211                        + "for identifier '" + identifier + "' in "
212                        + o.getClass() + " : " + e);
213        }
214 
215        return null;
216    }
217}

[all classes][org.apache.velocity.runtime.parser.node]
EMMA 2.0.4015 (stable) (C) Vladimir Roubtsov