aboutsummaryrefslogtreecommitdiff
path: root/velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java
blob: e53900201193dbdd14bff1b45e62a1f035274100 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
package org.apache.velocity.app.event;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.util.introspection.Info;


/**
 * Calls on request all registered event handlers for a particular event. Each
 * method accepts two event cartridges (typically one from the application and
 * one from the context). All appropriate event handlers are executed in order
 * until a stopping condition is met. See the docs for the individual methods to
 * see what the stopping condition is for that method.
 *
 * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a>
 * @version $Id$
 * @since 1.5
 */
public class EventHandlerUtil {


    /**
     * Called before a reference is inserted. All event handlers are called in
     * sequence. The default implementation inserts the reference as is.
     *
     * This is a major hotspot method called by ASTReference render.
     *
     * @param reference reference from template about to be inserted
     * @param value value about to be inserted (after toString() )
     * @param rsvc current instance of RuntimeServices
     * @param context The internal context adapter.
     * @return Object on which toString() should be called for output.
     */
    public static Object referenceInsert(RuntimeServices rsvc,
            InternalContextAdapter context, String reference, Object value)
    {
        try
        {
            value = rsvc.getApplicationEventCartridge().referenceInsert(context, reference, value);
            EventCartridge contextCartridge = context.getEventCartridge();
            if (contextCartridge != null)
            {
                contextCartridge.setRuntimeServices(rsvc);
                value = contextCartridge.referenceInsert(context, reference, value);
            }
            return value;
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new VelocityException("Exception in event handler.",e, rsvc.getLogContext().getStackTrace());
        }
    }

    /**
     * Called when a method exception is generated during Velocity merge. Only
     * the first valid event handler in the sequence is called. The default
     * implementation simply rethrows the exception.
     *
     * @param claz
     *            Class that is causing the exception
     * @param method
     *            method called that causes the exception
     * @param e
     *            Exception thrown by the method
     * @param rsvc current instance of RuntimeServices
     * @param context The internal context adapter.
     * @param info exception location informations
     * @return Object to return as method result
     * @throws Exception
     *             to be wrapped and propagated to app
     */
    public static Object methodException(RuntimeServices rsvc,
            InternalContextAdapter context, Class<?> claz, String method,
            Exception e, Info info) throws Exception
    {
        try
        {
            EventCartridge ev = rsvc.getApplicationEventCartridge();
            if (ev.hasMethodExceptionEventHandler())
            {
                return ev.methodException(context, claz, method, e, info);
            }
            EventCartridge contextCartridge = context.getEventCartridge();
            if (contextCartridge != null)
            {
                contextCartridge.setRuntimeServices(rsvc);
                return contextCartridge.methodException(context, claz, method, e, info);
            }
        }
        catch (RuntimeException re)
        {
            throw re;
        }
        catch (Exception ex)
        {
            throw new VelocityException("Exception in event handler.", ex, rsvc.getLogContext().getStackTrace());
        }

        /* default behaviour is to re-throw exception */
        throw e;
    }

    /**
     * Called when an include-type directive is encountered (#include or
     * #parse). All the registered event handlers are called unless null is
     * returned. The default implementation always processes the included
     * resource.
     *
     * @param includeResourcePath
     *            the path as given in the include directive.
     * @param currentResourcePath
     *            the path of the currently rendering template that includes the
     *            include directive.
     * @param directiveName
     *            name of the directive used to include the resource. (With the
     *            standard directives this is either "parse" or "include").
     * @param rsvc current instance of RuntimeServices
     * @param context The internal context adapter.
     *
     * @return a new resource path for the directive, or null to block the
     *         include from occurring.
     */
    public static String includeEvent(RuntimeServices rsvc,
            InternalContextAdapter context, String includeResourcePath,
            String currentResourcePath, String directiveName)
    {
        try
        {
            includeResourcePath = rsvc.getApplicationEventCartridge().includeEvent(context, includeResourcePath, currentResourcePath, directiveName);
            EventCartridge contextCartridge = context.getEventCartridge();
            if (contextCartridge != null)
            {
                contextCartridge.setRuntimeServices(rsvc);
                includeResourcePath = contextCartridge.includeEvent(context, includeResourcePath, currentResourcePath, directiveName);
            }
            return includeResourcePath;
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace());
        }
    }


    /**
     * Called when an invalid get method is encountered.
     *
     * @param rsvc current instance of RuntimeServices
     * @param context the context when the reference was found invalid
     * @param reference complete invalid reference
     * @param object object from reference, or null if not available
     * @param property name of property, or null if not relevant
     * @param info contains info on template, line, col
     * @return substitute return value for missing reference, or null if no substitute
     */
    public static Object invalidGetMethod(RuntimeServices rsvc,
            InternalContextAdapter context, String reference,
            Object object, String property, Info info)
    {
        try
        {
            Object result = rsvc.getApplicationEventCartridge().invalidGetMethod(context, reference, object, property, info);
            EventCartridge contextCartridge = context.getEventCartridge();
            if (contextCartridge != null)
            {
                contextCartridge.setRuntimeServices(rsvc);
                result = contextCartridge.invalidGetMethod(context, reference, object, property, info);
            }
            return result;
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace());
        }
    }

   /**
     * Called when an invalid set method is encountered.
     *
     * @param rsvc current instance of RuntimeServices
     * @param context the context when the reference was found invalid
     * @param leftreference left reference being assigned to
     * @param rightreference invalid reference on the right
     * @param info contains info on template, line, col
     */
    public static void invalidSetMethod(RuntimeServices rsvc,
            InternalContextAdapter context, String leftreference,
            String rightreference, Info info)
    {
        try
        {
            if (!rsvc.getApplicationEventCartridge().invalidSetMethod(context, leftreference, rightreference, info))
            {
                EventCartridge contextCartridge = context.getEventCartridge();
                if (contextCartridge != null)
                {
                    contextCartridge.setRuntimeServices(rsvc);
                    contextCartridge.invalidSetMethod(context, leftreference, rightreference, info);
                }
            }
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace());
        }
    }

    /**
     * Called when an invalid method is encountered.
     *
     * @param rsvc current instance of RuntimeServices
     * @param context the context when the reference was found invalid
     * @param reference complete invalid reference
     * @param object object from reference, or null if not available
     * @param method name of method, or null if not relevant
     * @param info contains info on template, line, col
     * @return substitute return value for missing reference, or null if no substitute
     */
    public static Object invalidMethod(RuntimeServices rsvc,
            InternalContextAdapter context,  String reference,
            Object object, String method, Info info)
    {
        try
        {
            Object result = rsvc.getApplicationEventCartridge().invalidMethod(context, reference, object, method, info);
            EventCartridge contextCartridge = context.getEventCartridge();
            if (contextCartridge != null)
            {
                contextCartridge.setRuntimeServices(rsvc);
                result = contextCartridge.invalidMethod(context, reference, object, method, info);
            }
            return result;
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace());
        }
    }
}