Source code: org/apache/struts/validator/ValidatorPlugIn.java
1 /*
2 * $Id: ValidatorPlugIn.java 105785 2004-11-19 06:58:36Z mrdon $
3 *
4 * Copyright 2000-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
19 package org.apache.struts.validator;
20
21 import org.xml.sax.SAXException;
22
23 import java.util.StringTokenizer;
24 import java.util.List;
25 import java.util.ArrayList;
26 import java.util.Iterator;
27 import java.io.BufferedInputStream;
28 import java.io.InputStream;
29 import java.io.IOException;
30 import javax.servlet.ServletException;
31 import javax.servlet.UnavailableException;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.commons.validator.ValidatorResources;
36 import org.apache.struts.action.ActionServlet;
37 import org.apache.struts.action.PlugIn;
38 import org.apache.struts.config.ModuleConfig;
39
40 /**
41 * Loads <code>ValidatorResources</code> based on configuration in the
42 * struts-config.xml file.
43 *
44 * @version $Rev: 105785 $ $Date: 2004-11-18 22:58:36 -0800 (Thu, 18 Nov 2004) $
45 * @since Struts 1.1
46 */
47 public class ValidatorPlugIn implements PlugIn {
48
49 /**
50 * Commons Logging instance.
51 */
52 private static Log log = LogFactory.getLog(ValidatorPlugIn.class);
53
54 /**
55 * The module configuration for our owning module.
56 */
57 private ModuleConfig config = null;
58
59 /**
60 * The {@link ActionServlet} owning this application.
61 */
62 private ActionServlet servlet = null;
63
64 /**
65 * Delimitter for Validator resources.
66 */
67 private final static String RESOURCE_DELIM = ",";
68
69 /**
70 * Application scope key that <code>ValidatorResources</code> is stored under.
71 */
72 public final static String VALIDATOR_KEY =
73 "org.apache.commons.validator.VALIDATOR_RESOURCES";
74
75 /**
76 * Application scope key that <code>StopOnError</code> is stored under.
77 *
78 * @since Struts 1.2
79 */
80 public final static String STOP_ON_ERROR_KEY =
81 "org.apache.struts.validator.STOP_ON_ERROR";
82
83 /**
84 * The set of Form instances that have been created and initialized,
85 * keyed by the struts form name.
86 */
87 protected ValidatorResources resources = null;
88
89
90 // ------------------------------------------------------------- Properties
91
92 /**
93 * A comma delimitted list of Validator resource.
94 */
95 private String pathnames = null;
96
97 /**
98 * Gets a comma delimitted list of Validator resources.
99 *
100 * @return comma delimited list of Validator resource path names
101 */
102 public String getPathnames() {
103 return pathnames;
104 }
105
106 /**
107 * Sets a comma delimitted list of Validator resources.
108 *
109 * @param pathnames delimited list of Validator resource path names
110 */
111 public void setPathnames(String pathnames) {
112 this.pathnames = pathnames;
113 }
114
115 /**
116 * Informs the Validators if it has to stop validation when finding the
117 * first error or if it should continue. Default to <code>true</code> to
118 * keep Struts 1.1 backwards compatibility.
119 */
120 private boolean stopOnFirstError = true;
121
122 /**
123 * Gets the value for stopOnFirstError.
124 *
125 * @return A boolean indicating whether JavaScript validation should stop
126 * when it finds the first error (Struts 1.1 behaviour) or continue
127 * validation.
128 * @since Struts 1.2
129 */
130 public boolean isStopOnFirstError() {
131 return this.stopOnFirstError;
132 }
133
134 /**
135 * Sets the value for stopOnFirstError.
136 *
137 * @param stopOnFirstError A boolean indicating whether JavaScript
138 * validation should stop when it finds the first error
139 * (Struts 1.1 behaviour) or continue validation.
140 * @since Struts 1.2
141 */
142 public void setStopOnFirstError(boolean stopOnFirstError) {
143 this.stopOnFirstError = stopOnFirstError;
144 }
145
146 /**
147 * Initialize and load our resources.
148 *
149 * @param servlet The ActionServlet for our application
150 * @param config The ModuleConfig for our owning module
151 * @throws ServletException if we cannot configure ourselves correctly
152 */
153 public void init(ActionServlet servlet, ModuleConfig config)
154 throws ServletException {
155
156 // Remember our associated configuration and servlet
157 this.config = config;
158 this.servlet = servlet;
159
160 // Load our database from persistent storage
161 try {
162 this.initResources();
163
164 servlet.getServletContext().setAttribute(VALIDATOR_KEY + config.getPrefix(),
165 resources);
166
167 servlet.getServletContext().setAttribute(STOP_ON_ERROR_KEY + '.' + config.getPrefix(),
168 (this.stopOnFirstError ? Boolean.TRUE : Boolean.FALSE));
169
170 } catch (Exception e) {
171 log.error(e.getMessage(), e);
172 throw new UnavailableException("Cannot load a validator resource from '" + pathnames + "'");
173 }
174
175 }
176
177 /**
178 * Gracefully shut down, releasing any resources
179 * that were allocated at initialization.
180 */
181 public void destroy() {
182
183 if (log.isDebugEnabled()) {
184 log.debug("Destroying ValidatorPlugin");
185 }
186
187 servlet = null;
188 config = null;
189
190 destroyResources();
191 }
192
193 /**
194 * Initialize the validator resources for this module.
195 *
196 * @throws IOException if an input/output error is encountered
197 * @throws ServletException if we cannot initialize these resources
198 */
199 protected void initResources() throws IOException, ServletException {
200
201 if (pathnames == null || pathnames.length() <= 0) {
202 return;
203 }
204 StringTokenizer st = new StringTokenizer(pathnames, RESOURCE_DELIM);
205
206 List streamList = new ArrayList();
207 try {
208 while (st.hasMoreTokens()) {
209 String validatorRules = st.nextToken().trim();
210 if (log.isInfoEnabled()) {
211 log.info("Loading validation rules file from '" + validatorRules + "'");
212 }
213
214 InputStream input = servlet.getServletContext().getResourceAsStream(validatorRules);
215
216 // If the config isn't in the servlet context, try the class loader
217 // which allows the config files to be stored in a jar
218 if (input == null) {
219 input = getClass().getResourceAsStream(validatorRules);
220 }
221
222 if (input != null) {
223 BufferedInputStream bis = new BufferedInputStream(input);
224 streamList.add(bis);
225 } else {
226 throw new ServletException("Skipping validation rules file from '"
227 + validatorRules + "'. No stream could be opened.");
228 }
229 }
230 int streamSize = streamList.size();
231 InputStream[] streamArray = new InputStream[streamSize];
232 for (int streamIndex = 0;streamIndex < streamSize;streamIndex++) {
233 InputStream is = (InputStream) streamList.get(streamIndex);
234 streamArray[streamIndex] = is;
235 }
236
237 this.resources = new ValidatorResources(streamArray);
238 } catch (SAXException sex) {
239 log.error("Skipping all validation",sex);
240 throw new ServletException(sex);
241 } finally {
242 Iterator streamIterator = streamList.iterator();
243 while (streamIterator.hasNext()) {
244 InputStream is = (InputStream) streamIterator.next();
245 is.close();
246 }
247 }
248
249 }
250
251 /**
252 * Destroy <code>ValidatorResources</code>.
253 */
254 protected void destroyResources() {
255 resources = null;
256 }
257
258 }