001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.catalina.ssi;
018:
019: import java.io.PrintWriter;
020: import java.text.ParseException;
021:
022: /**
023: * SSI command that handles all conditional directives.
024: *
025: * @version $Revision: 531303 $
026: * @author Paul Speed
027: * @author David Becker
028: */
029: public class SSIConditional implements SSICommand {
030: /**
031: * @see SSICommand
032: */
033: public long process(SSIMediator ssiMediator, String commandName,
034: String[] paramNames, String[] paramValues,
035: PrintWriter writer) throws SSIStopProcessingException {
036: // Assume anything using conditionals was modified by it
037: long lastModified = System.currentTimeMillis();
038: // Retrieve the current state information
039: SSIConditionalState state = ssiMediator.getConditionalState();
040: if ("if".equalsIgnoreCase(commandName)) {
041: // Do nothing if we are nested in a false branch
042: // except count it
043: if (state.processConditionalCommandsOnly) {
044: state.nestingCount++;
045: return lastModified;
046: }
047: state.nestingCount = 0;
048: // Evaluate the expression
049: if (evaluateArguments(paramNames, paramValues, ssiMediator)) {
050: // No more branches can be taken for this if block
051: state.branchTaken = true;
052: } else {
053: // Do not process this branch
054: state.processConditionalCommandsOnly = true;
055: state.branchTaken = false;
056: }
057: } else if ("elif".equalsIgnoreCase(commandName)) {
058: // No need to even execute if we are nested in
059: // a false branch
060: if (state.nestingCount > 0)
061: return lastModified;
062: // If a branch was already taken in this if block
063: // then disable output and return
064: if (state.branchTaken) {
065: state.processConditionalCommandsOnly = true;
066: return lastModified;
067: }
068: // Evaluate the expression
069: if (evaluateArguments(paramNames, paramValues, ssiMediator)) {
070: // Turn back on output and mark the branch
071: state.processConditionalCommandsOnly = false;
072: state.branchTaken = true;
073: } else {
074: // Do not process this branch
075: state.processConditionalCommandsOnly = true;
076: state.branchTaken = false;
077: }
078: } else if ("else".equalsIgnoreCase(commandName)) {
079: // No need to even execute if we are nested in
080: // a false branch
081: if (state.nestingCount > 0)
082: return lastModified;
083: // If we've already taken another branch then
084: // disable output otherwise enable it.
085: state.processConditionalCommandsOnly = state.branchTaken;
086: // And in any case, it's safe to say a branch
087: // has been taken.
088: state.branchTaken = true;
089: } else if ("endif".equalsIgnoreCase(commandName)) {
090: // If we are nested inside a false branch then pop out
091: // one level on the nesting count
092: if (state.nestingCount > 0) {
093: state.nestingCount--;
094: return lastModified;
095: }
096: // Turn output back on
097: state.processConditionalCommandsOnly = false;
098: // Reset the branch status for any outer if blocks,
099: // since clearly we took a branch to have gotten here
100: // in the first place.
101: state.branchTaken = true;
102: } else {
103: throw new SSIStopProcessingException();
104: //throw new SsiCommandException( "Not a conditional command:" +
105: // cmdName );
106: }
107: return lastModified;
108: }
109:
110: /**
111: * Retrieves the expression from the specified arguments and peforms the
112: * necessary evaluation steps.
113: */
114: private boolean evaluateArguments(String[] names, String[] values,
115: SSIMediator ssiMediator) throws SSIStopProcessingException {
116: String expr = getExpression(names, values);
117: if (expr == null) {
118: throw new SSIStopProcessingException();
119: //throw new SsiCommandException( "No expression specified." );
120: }
121: try {
122: ExpressionParseTree tree = new ExpressionParseTree(expr,
123: ssiMediator);
124: return tree.evaluateTree();
125: } catch (ParseException e) {
126: //throw new SsiCommandException( "Error parsing expression." );
127: throw new SSIStopProcessingException();
128: }
129: }
130:
131: /**
132: * Returns the "expr" if the arg name is appropriate, otherwise returns
133: * null.
134: */
135: private String getExpression(String[] paramNames,
136: String[] paramValues) {
137: if ("expr".equalsIgnoreCase(paramNames[0]))
138: return paramValues[0];
139: return null;
140: }
141: }
|