1 package org.apache.velocity.app.event.implement;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.velocity.app.event.InvalidReferenceEventHandler;
26 import org.apache.velocity.context.Context;
27 import org.apache.velocity.exception.ParseErrorException;
28 import org.apache.velocity.runtime.RuntimeServices;
29 import org.apache.velocity.util.RuntimeServicesAware;
30 import org.apache.velocity.util.introspection.Info;
31
32 /**
33 * Use this event handler to flag invalid references. Since this
34 * is intended to be used for a specific request, this should be
35 * used as a local event handler attached to a specific context
36 * instead of being globally defined in the Velocity properties file.
37 *
38 * <p>
39 * Note that InvalidReferenceHandler can be used
40 * in two modes. If the Velocity properties file contains the following:
41 * <pre>
42 * eventhandler.invalidreference.exception = true
43 * </pre>
44 * then the event handler will throw a ParseErrorRuntimeException upon
45 * hitting the first invalid reference. This stops processing and is
46 * passed through to the application code. The ParseErrorRuntimeException
47 * contain information about the template name, line number, column number,
48 * and invalid reference.
49 *
50 * <p>
51 * If this configuration setting is false or omitted then the page
52 * will be processed as normal, but all invalid references will be collected
53 * in a List of InvalidReferenceInfo objects.
54 *
55 * <p>This feature should be regarded as experimental.
56 *
57 * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
58 * @version $Id: ReportInvalidReferences.java 470265 2006-11-02 07:45:02Z wglass $
59 */
60 public class ReportInvalidReferences implements
61 InvalidReferenceEventHandler, RuntimeServicesAware
62 {
63
64 public static final String EVENTHANDLER_INVALIDREFERENCE_EXCEPTION = "eventhandler.invalidreference.exception";
65
66 /**
67 * List of InvalidReferenceInfo objects
68 */
69 List invalidReferences = new ArrayList();
70
71 /**
72 * If true, stop at the first invalid reference and throw an exception.
73 */
74 private boolean stopOnFirstInvalidReference = false;
75
76
77 /**
78 * Collect the error and/or throw an exception, depending on configuration.
79 *
80 * @param context the context when the reference was found invalid
81 * @param reference string with complete invalid reference
82 * @param object the object referred to, or null if not found
83 * @param property the property name from the reference
84 * @param info contains template, line, column details
85 * @return always returns null
86 * @throws ParseErrorException
87 */
88 public Object invalidGetMethod(Context context, String reference, Object object,
89 String property, Info info)
90 {
91 reportInvalidReference(reference, info);
92 return null;
93 }
94
95 /**
96 * Collect the error and/or throw an exception, depending on configuration.
97 *
98 * @param context the context when the reference was found invalid
99 * @param reference complete invalid reference
100 * @param object the object referred to, or null if not found
101 * @param method the property name from the reference
102 * @param info contains template, line, column details
103 * @return always returns null
104 * @throws ParseErrorException
105 */
106 public Object invalidMethod(Context context, String reference, Object object,
107 String method, Info info)
108 {
109 if (reference == null)
110 {
111 reportInvalidReference(object.getClass().getName() + "." + method, info);
112 }
113 else
114 {
115 reportInvalidReference(reference, info);
116 }
117 return null;
118 }
119
120 /**
121 * Collect the error and/or throw an exception, depending on configuration.
122 *
123 * @param context the context when the reference was found invalid
124 * @param leftreference left reference being assigned to
125 * @param rightreference invalid reference on the right
126 * @param info contains info on template, line, col
127 * @return loop to end -- always returns false
128 */
129 public boolean invalidSetMethod(Context context, String leftreference, String rightreference, Info info)
130 {
131 reportInvalidReference(leftreference, info);
132 return false;
133 }
134
135
136 /**
137 * Check for an invalid reference and collect the error or throw an exception
138 * (depending on configuration).
139 *
140 * @param reference the invalid reference
141 * @param info line, column, template name
142 */
143 private void reportInvalidReference(String reference, Info info)
144 {
145 InvalidReferenceInfo invalidReferenceInfo = new InvalidReferenceInfo(reference, info);
146 invalidReferences.add(invalidReferenceInfo);
147
148 if (stopOnFirstInvalidReference)
149 {
150 throw new ParseErrorException(
151 "Error in page - invalid reference. ",
152 info,
153 invalidReferenceInfo.getInvalidReference());
154 }
155 }
156
157
158 /**
159 * All invalid references during the processing of this page.
160 * @return a List of InvalidReferenceInfo objects
161 */
162 public List getInvalidReferences()
163 {
164 return invalidReferences;
165 }
166
167
168 /**
169 * Called automatically when event cartridge is initialized.
170 * @param rs RuntimeServices object assigned during initialization
171 */
172 public void setRuntimeServices(RuntimeServices rs)
173 {
174 stopOnFirstInvalidReference = rs.getConfiguration().getBoolean(
175 EVENTHANDLER_INVALIDREFERENCE_EXCEPTION,
176 false);
177 }
178
179 }