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.validwhen;
22  
23  import jakarta.servlet.http.HttpServletRequest;
24  
25  import org.antlr.v4.runtime.CharStreams;
26  import org.antlr.v4.runtime.CommonTokenStream;
27  import org.apache.commons.validator.Field;
28  import org.apache.commons.validator.Validator;
29  import org.apache.commons.validator.ValidatorAction;
30  import org.apache.commons.validator.util.ValidatorUtils;
31  import org.apache.struts.action.ActionMessage;
32  import org.apache.struts.action.ActionMessages;
33  import org.apache.struts.util.MessageResources;
34  import org.apache.struts.validator.Resources;
35  import org.apache.struts.validator.validwhen.ValidWhenParser.ExpressionContext;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * This class contains the validwhen validation that is used in the
41   * validator-rules.xml file.
42   *
43   * @since Struts 1.2
44   */
45  public class ValidWhen {
46  
47      /**
48       * The {@code Log} instance for this class.
49       */
50      private final static Logger LOG =
51          LoggerFactory.getLogger(ValidWhen.class);
52  
53      /**
54       * The message resources for this package.
55       */
56      private static MessageResources sysmsgs =
57          MessageResources.getMessageResources(
58              "org.apache.struts.validator.LocalStrings");
59  
60      /**
61       * Returns true if <code>obj</code> is null or a String.
62       */
63      private static boolean isString(Object obj) {
64          return (obj == null) ? true : String.class.isInstance(obj);
65      }
66  
67      /**
68       * Checks if the field matches the boolean expression specified in
69       * <code>test</code> parameter.
70       *
71       * @param bean    The bean validation is being performed on.
72       * @param va      The <code>ValidatorAction</code> that is currently being
73       *                performed.
74       * @param field   The <code>Field</code> object associated with the
75       *                current field being validated.
76       * @param errors  The <code>ActionMessages</code> object to add errors to
77       *                if any validation errors occur.
78       * @param request Current request object.
79       * @return <code>true</code> if meets stated requirements,
80       *         <code>false</code> otherwise.
81       */
82      public static boolean validateValidWhen(Object bean, ValidatorAction va,
83          Field field, ActionMessages errors, Validator validator,
84          HttpServletRequest request) {
85          Object form = validator.getParameterValue(Validator.BEAN_PARAM);
86          String value = null;
87          boolean valid = false;
88          int index = -1;
89  
90          if (field.isIndexed()) {
91              String key = field.getKey();
92  
93              final int leftBracket = key.indexOf("[");
94              final int rightBracket = key.indexOf("]");
95  
96              if ((leftBracket > -1) && (rightBracket > -1)) {
97                  index =
98                      Integer.parseInt(key.substring(leftBracket + 1,
99                          rightBracket));
100             }
101         }
102 
103         if (isString(bean)) {
104             value = (String) bean;
105         } else {
106             value = ValidatorUtils.getValueAsString(bean, field.getProperty());
107         }
108 
109         String test = null;
110 
111         try {
112             test =
113                 Resources.getVarValue("test", field, validator, request, true);
114         } catch (IllegalArgumentException ex) {
115             LOG.atError().log(() -> sysmsgs.getMessage("validation.failed", "validwhen",
116                 field.getProperty(), validator.getFormName(), ex.toString()));
117 
118             String userErrorMsg = sysmsgs.getMessage("system.error");
119 
120             errors.add(field.getKey(), new ActionMessage(userErrorMsg, false));
121 
122             return false;
123         }
124 
125         // Create the Lexer
126         ValidWhenLexer lexer = null;
127 
128         try {
129             lexer = new ValidWhenLexer(CharStreams.fromString(test));
130         } catch (Exception ex) {
131             LOG.error("ValidWhenLexer Error for field '{}'",
132                 field.getKey(), ex);
133 
134             String userErrorMsg = sysmsgs.getMessage("system.error");
135 
136             errors.add(field.getKey(), new ActionMessage(userErrorMsg, false));
137 
138             return false;
139         }
140 
141         // Create the Parser
142         ValidWhenParser parser = null;
143 
144         try {
145             parser = new ValidWhenParser(new CommonTokenStream(lexer));
146         } catch (Exception ex) {
147             LOG.error("ValidWhenParser Error for field '{}'",
148                 field.getKey(), ex);
149 
150             String userErrorMsg = sysmsgs.getMessage("system.error");
151 
152             errors.add(field.getKey(), new ActionMessage(userErrorMsg, false));
153 
154             return false;
155         }
156 
157         ValidWhenEvaluator validWhenEvaluator = new ValidWhenEvaluator(form, value, index);
158 
159         try {
160             ExpressionContext expressionContext = parser.expression();
161             ValidWhenResult<?> result = validWhenEvaluator.visitExpression(expressionContext);
162             valid = result == null ? false : result.toBoolean();
163         } catch (Exception ex) {
164             LOG.error("ValidWhen Error for field '{}'",
165                 field.getKey(), ex);
166 
167             String userErrorMsg = sysmsgs.getMessage("system.error");
168 
169             errors.add(field.getKey(), new ActionMessage(userErrorMsg, false));
170 
171             return false;
172         }
173 
174         if (!valid) {
175             errors.add(field.getKey(),
176                 Resources.getActionMessage(validator, request, va, field));
177 
178             return false;
179         }
180 
181         return true;
182     }
183 }