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