View Javadoc

1   /*
2    * $Id: ActionFormValidationInterceptor.java 651946 2008-04-27 13:41:38Z apetrelli $
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  package org.apache.struts2.s1;
23  
24  import java.io.IOException;
25  import java.net.URL;
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.StringTokenizer;
29  
30  import javax.servlet.ServletContext;
31  import javax.servlet.ServletException;
32  import javax.servlet.http.HttpServletRequest;
33  
34  import org.apache.commons.validator.ValidatorResources;
35  import org.apache.struts.Globals;
36  import org.apache.struts.action.ActionErrors;
37  import org.apache.struts.action.ActionForm;
38  import org.apache.struts.action.ActionMapping;
39  import org.apache.struts.action.ActionServlet;
40  import org.apache.struts.config.ModuleConfig;
41  import org.apache.struts.validator.ValidatorPlugIn;
42  import org.apache.struts2.ServletActionContext;
43  import org.apache.struts2.StrutsException;
44  import org.xml.sax.SAXException;
45  
46  import com.opensymphony.xwork2.ActionContext;
47  import com.opensymphony.xwork2.ActionInvocation;
48  import com.opensymphony.xwork2.TextProvider;
49  import com.opensymphony.xwork2.config.Configuration;
50  import com.opensymphony.xwork2.inject.Inject;
51  import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
52  import com.opensymphony.xwork2.interceptor.ScopedModelDriven;
53  import com.opensymphony.xwork2.util.logging.Logger;
54  import com.opensymphony.xwork2.util.logging.LoggerFactory;
55  
56  /***
57   *  Calls the validate() method on the ActionForm, if it exists.  The errors are handled
58   *  like regular XWork validation errors.  Action-level validation flag supported if the
59   *  action is a subclass of Struts1Action.
60   */
61  public class ActionFormValidationInterceptor extends AbstractInterceptor {
62  
63      private String pathnames;
64      private boolean stopOnFirstError;
65      private boolean initialized = false;
66      
67      private static final Logger LOG = LoggerFactory.getLogger(ActionFormValidationInterceptor.class);
68      
69      /***
70       * Delimitter for Validator resources.
71       */
72      private final static String RESOURCE_DELIM = ",";
73      
74      protected Configuration configuration;
75  
76      @Inject
77      public void setConfiguration(Configuration config) {
78          this.configuration = config;
79      }
80      
81      /***
82       * Initializes the validation resources
83       */
84      private void initResources(ServletContext servletContext) {
85          if (pathnames != null) {
86              ActionContext ctx = ActionContext.getContext();
87              try {
88                  
89                  ValidatorResources resources = this.loadResources(servletContext);
90      
91                  
92                  String prefix = ctx.getActionInvocation().getProxy().getNamespace();
93                  
94                  
95                  servletContext.setAttribute(ValidatorPlugIn.VALIDATOR_KEY + prefix, resources);
96      
97                  servletContext.setAttribute(ValidatorPlugIn.STOP_ON_ERROR_KEY + '.'
98                      + prefix,
99                      (this.stopOnFirstError ? Boolean.TRUE : Boolean.FALSE));
100             } catch (Exception e) {
101                 throw new StrutsException(
102                     "Cannot load a validator resource from '" + pathnames + "'", e);
103             }
104         }
105     }
106 
107     @Override
108     public String intercept(ActionInvocation invocation) throws Exception {
109         // Lazy load the resources because the servlet context isn't available at init() time
110         synchronized (this) {
111             if (!initialized) {
112                 initResources(ServletActionContext.getServletContext());
113                 initialized = true;
114             }
115         }
116         Object action = invocation.getAction();
117 
118         
119         if ((action instanceof ScopedModelDriven) &&
120             (!(action instanceof Struts1Action) || ((Struts1Action)action).isValidate())) {
121             ScopedModelDriven modelDriven = (ScopedModelDriven) action;
122             Object model = modelDriven.getModel();
123             if (model != null) {
124                 HttpServletRequest req = ServletActionContext.getRequest();
125                 Struts1Factory strutsFactory = new Struts1Factory(configuration);
126                 ActionMapping mapping = strutsFactory.createActionMapping(invocation.getProxy().getConfig());
127                 ModuleConfig moduleConfig = strutsFactory.createModuleConfig(invocation.getProxy().getConfig().getPackageName());
128                 req.setAttribute(Globals.MODULE_KEY, moduleConfig);
129                 req.setAttribute(Globals.MESSAGES_KEY, new WrapperMessageResources((TextProvider)invocation.getAction()));
130                 
131                 mapping.setAttribute(modelDriven.getScopeKey());
132                 
133                 ActionForm form = (ActionForm) model;
134                 form.setServlet(new ActionServlet(){
135                     public ServletContext getServletContext() {
136                         return ServletActionContext.getServletContext();
137                     }
138                 });
139                 ActionErrors errors = form.validate(mapping, req);
140                 strutsFactory.convertErrors(errors, action);                
141             }
142         }
143         return invocation.invoke();
144     }
145     
146     /***
147      * Initialize the validator resources for this module.
148      *
149      * @throws IOException      if an input/output error is encountered
150      * @throws ServletException if we cannot initialize these resources
151      */
152     protected ValidatorResources loadResources(ServletContext ctx)
153         throws IOException, ServletException {
154         if ((pathnames == null) || (pathnames.length() <= 0)) {
155             return null;
156         }
157 
158         StringTokenizer st = new StringTokenizer(pathnames, RESOURCE_DELIM);
159 
160         List urlList = new ArrayList();
161         ValidatorResources resources = null;
162         try {
163             while (st.hasMoreTokens()) {
164                 String validatorRules = st.nextToken().trim();
165 
166                 if (LOG.isInfoEnabled()) {
167                     LOG.info("Loading validation rules file from '"
168                         + validatorRules + "'");
169                 }
170 
171                 URL input =
172                     ctx.getResource(validatorRules);
173 
174                 // If the config isn't in the servlet context, try the class
175                 // loader which allows the config files to be stored in a jar
176                 if (input == null) {
177                     input = getClass().getResource(validatorRules);
178                 }
179 
180                 if (input != null) {
181                     urlList.add(input);
182                 } else {
183                     throw new ServletException(
184                         "Skipping validation rules file from '"
185                         + validatorRules + "'.  No url could be located.");
186                 }
187             }
188 
189             int urlSize = urlList.size();
190             String[] urlArray = new String[urlSize];
191 
192             for (int urlIndex = 0; urlIndex < urlSize; urlIndex++) {
193                 URL url = (URL) urlList.get(urlIndex);
194 
195                 urlArray[urlIndex] = url.toExternalForm();
196             }
197 
198             resources =  new ValidatorResources(urlArray);
199         } catch (SAXException sex) {
200             LOG.error("Skipping all validation", sex);
201             throw new StrutsException("Skipping all validation because the validation files cannot be loaded", sex);
202         }
203         return resources;
204     }
205 
206     /***
207      * @return the pathnames
208      */
209     public String getPathnames() {
210         return pathnames;
211     }
212 
213     /***
214      * @param pathNames the pathnames to set
215      */
216     public void setPathnames(String pathNames) {
217         this.pathnames = pathNames;
218     }
219 
220     /***
221      * @return the stopOnFirstError
222      */
223     public boolean isStopOnFirstError() {
224         return stopOnFirstError;
225     }
226 
227     /***
228      * @param stopOnFirstError the stopOnFirstError to set
229      */
230     public void setStopOnFirstError(boolean stopOnFirstError) {
231         this.stopOnFirstError = stopOnFirstError;
232     }
233 
234 }