View Javadoc

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