aboutsummaryrefslogtreecommitdiff
path: root/velocity-engine-core/src/main/java/org/apache/velocity/app/event/implement/ReportInvalidReferences.java
blob: de09f84e2554d634e62aa049bf6ee33d6780727e (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
package org.apache.velocity.app.event.implement;

/*
 * 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.app.event.InvalidReferenceEventHandler;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.util.RuntimeServicesAware;
import org.apache.velocity.util.introspection.Info;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * Use this event handler to flag invalid references.  Since this
 * is intended to be used for a specific request, this should be
 * used as a local event handler attached to a specific context
 * instead of being globally defined in the Velocity properties file.
 *
 * <p>
 * Note that InvalidReferenceHandler can be used
 * in two modes.  If the Velocity properties file contains the following:
 * <pre>
 * event_handler.invalid_references.exception = true
 * </pre>
 * then the event handler will throw a ParseErrorRuntimeException upon
 * hitting the first invalid reference.  This stops processing and is
 * passed through to the application code.  The ParseErrorRuntimeException
 * contain information about the template name, line number, column number,
 * and invalid reference.
 *
 * <p>
 * If this configuration setting is false or omitted then the page
 * will be processed as normal, but all invalid references will be collected
 * in a List of InvalidReferenceInfo objects.
 *
 * <p>This feature should be regarded as experimental.
 *
 * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
 * @version $Id$
 * @since 1.5
 */
public class ReportInvalidReferences implements
    InvalidReferenceEventHandler, RuntimeServicesAware
{
    public static final String EVENTHANDLER_INVALIDREFERENCE_EXCEPTION = "event_handler.invalid_references.exception";

    @Deprecated
    public static final String OLD_EVENTHANDLER_INVALIDREFERENCE_EXCEPTION = "eventhandler.invalidreference.exception";

    /**
     * List of InvalidReferenceInfo objects
     */
    List<InvalidReferenceInfo> invalidReferences = new ArrayList();

    /**
     * If true, stop at the first invalid reference and throw an exception.
     */
    private boolean stopOnFirstInvalidReference = false;


    /**
     * Collect the error and/or throw an exception, depending on configuration.
     *
     * @param context the context when the reference was found invalid
     * @param reference string with complete invalid reference
     * @param object the object referred to, or null if not found
     * @param property the property name from the reference
     * @param info contains template, line, column details
     * @return always returns null
     * @throws ParseErrorException
     */
    public Object invalidGetMethod(Context context, String reference, Object object,
            String property, Info info)
    {
        reportInvalidReference(reference, info);
        return null;
    }

    /**
     * Collect the error and/or throw an exception, depending on configuration.
     *
     * @param context the context when the reference was found invalid
     * @param reference complete invalid reference
     * @param object the object referred to, or null if not found
     * @param method the property name from the reference
     * @param info contains template, line, column details
     * @return always returns null
     * @throws ParseErrorException
     */
    public Object invalidMethod(Context context, String reference, Object object,
            String method, Info info)
    {
        if (reference == null)
        {
            reportInvalidReference(object.getClass().getName() + "." + method, info);
        }
        else
        {
            reportInvalidReference(reference, info);
        }
        return null;
    }

    /**
     * Collect the error and/or throw an exception, depending on configuration.
     *
     * @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
     * @return loop to end -- always returns false
     */
    public boolean invalidSetMethod(Context context, String leftreference, String rightreference, Info info)
    {
        reportInvalidReference(leftreference, info);
        return false;
    }


    /**
     * Check for an invalid reference and collect the error or throw an exception
     * (depending on configuration).
     *
     * @param reference the invalid reference
     * @param info line, column, template name
     */
    private void reportInvalidReference(String reference, Info info)
    {
        InvalidReferenceInfo invalidReferenceInfo = new InvalidReferenceInfo(reference, info);
        invalidReferences.add(invalidReferenceInfo);

        if (stopOnFirstInvalidReference)
        {
            throw new ParseErrorException(
                    "Error in page - invalid reference.  ",
                    info,
                    invalidReferenceInfo.getInvalidReference());
        }
    }


    /**
     * All invalid references during the processing of this page.
     * @return a List of InvalidReferenceInfo objects
     */
    public List<InvalidReferenceInfo> getInvalidReferences()
    {
        return invalidReferences;
    }


    /**
     * Called automatically when event cartridge is initialized.
     * @param rs RuntimeServices object assigned during initialization
     */
    public void setRuntimeServices(RuntimeServices rs)
    {
        Boolean b = rs.getConfiguration().getBoolean(OLD_EVENTHANDLER_INVALIDREFERENCE_EXCEPTION, null);
        if (b == null)
        {
            b = rs.getConfiguration().getBoolean(EVENTHANDLER_INVALIDREFERENCE_EXCEPTION, false);
        }
        else
        {
            rs.getLog().warn("configuration key '{}' has been deprecated in favor of '{}'", OLD_EVENTHANDLER_INVALIDREFERENCE_EXCEPTION, EVENTHANDLER_INVALIDREFERENCE_EXCEPTION);
        }
        stopOnFirstInvalidReference = b.booleanValue();
    }

}