| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.catalina.ssi; |
| |
| |
| import java.io.PrintWriter; |
| import java.text.ParseException; |
| /** |
| * SSI command that handles all conditional directives. |
| * |
| * @author Paul Speed |
| * @author David Becker |
| */ |
| public class SSIConditional implements SSICommand { |
| /** |
| * @see SSICommand |
| */ |
| @Override |
| public long process(SSIMediator ssiMediator, String commandName, |
| String[] paramNames, String[] paramValues, PrintWriter writer) |
| throws SSIStopProcessingException { |
| // Assume anything using conditionals was modified by it |
| long lastModified = System.currentTimeMillis(); |
| // Retrieve the current state information |
| SSIConditionalState state = ssiMediator.getConditionalState(); |
| if ("if".equalsIgnoreCase(commandName)) { |
| // Do nothing if we are nested in a false branch |
| // except count it |
| if (state.processConditionalCommandsOnly) { |
| state.nestingCount++; |
| return lastModified; |
| } |
| state.nestingCount = 0; |
| // Evaluate the expression |
| if (evaluateArguments(paramNames, paramValues, ssiMediator)) { |
| // No more branches can be taken for this if block |
| state.branchTaken = true; |
| } else { |
| // Do not process this branch |
| state.processConditionalCommandsOnly = true; |
| state.branchTaken = false; |
| } |
| } else if ("elif".equalsIgnoreCase(commandName)) { |
| // No need to even execute if we are nested in |
| // a false branch |
| if (state.nestingCount > 0) return lastModified; |
| // If a branch was already taken in this if block |
| // then disable output and return |
| if (state.branchTaken) { |
| state.processConditionalCommandsOnly = true; |
| return lastModified; |
| } |
| // Evaluate the expression |
| if (evaluateArguments(paramNames, paramValues, ssiMediator)) { |
| // Turn back on output and mark the branch |
| state.processConditionalCommandsOnly = false; |
| state.branchTaken = true; |
| } else { |
| // Do not process this branch |
| state.processConditionalCommandsOnly = true; |
| state.branchTaken = false; |
| } |
| } else if ("else".equalsIgnoreCase(commandName)) { |
| // No need to even execute if we are nested in |
| // a false branch |
| if (state.nestingCount > 0) return lastModified; |
| // If we've already taken another branch then |
| // disable output otherwise enable it. |
| state.processConditionalCommandsOnly = state.branchTaken; |
| // And in any case, it's safe to say a branch |
| // has been taken. |
| state.branchTaken = true; |
| } else if ("endif".equalsIgnoreCase(commandName)) { |
| // If we are nested inside a false branch then pop out |
| // one level on the nesting count |
| if (state.nestingCount > 0) { |
| state.nestingCount--; |
| return lastModified; |
| } |
| // Turn output back on |
| state.processConditionalCommandsOnly = false; |
| // Reset the branch status for any outer if blocks, |
| // since clearly we took a branch to have gotten here |
| // in the first place. |
| state.branchTaken = true; |
| } else { |
| throw new SSIStopProcessingException(); |
| //throw new SsiCommandException( "Not a conditional command:" + |
| // cmdName ); |
| } |
| return lastModified; |
| } |
| |
| |
| /** |
| * Retrieves the expression from the specified arguments and performs the |
| * necessary evaluation steps. |
| */ |
| private boolean evaluateArguments(String[] names, String[] values, |
| SSIMediator ssiMediator) throws SSIStopProcessingException { |
| String expr = getExpression(names, values); |
| if (expr == null) { |
| throw new SSIStopProcessingException(); |
| //throw new SsiCommandException( "No expression specified." ); |
| } |
| try { |
| ExpressionParseTree tree = new ExpressionParseTree(expr, |
| ssiMediator); |
| return tree.evaluateTree(); |
| } catch (ParseException e) { |
| //throw new SsiCommandException( "Error parsing expression." ); |
| throw new SSIStopProcessingException(); |
| } |
| } |
| |
| |
| /** |
| * Returns the "expr" if the arg name is appropriate, otherwise returns |
| * null. |
| */ |
| private String getExpression(String[] paramNames, String[] paramValues) { |
| if ("expr".equalsIgnoreCase(paramNames[0])) return paramValues[0]; |
| return null; |
| } |
| } |