amyroh 01/11/28 19:41:27 Modified: catalina/src/share/org/apache/catalina/util/ssi FileReference.java ResponseIncludeWrapper.java ServletOutputStreamWrapper.java SsiCommand.java SsiCommandException.java SsiConfig.java SsiDispatcher.java SsiEcho.java SsiEnvironment.java SsiExec.java SsiFlastmod.java SsiFsize.java SsiInclude.java SsiSet.java Added: catalina/src/share/org/apache/catalina/util/ssi AbstractSsiCommand.java ExpressionParseTree.java ExpressionTokenizer.java SsiConditional.java Log: Server Side Include improvement. Submitted by Paul Speed <[EMAIL PROTECTED]>. Revision Changes Path 1.2 +4 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/FileReference.java Index: FileReference.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/FileReference.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- FileReference.java 2001/10/26 19:35:23 1.1 +++ FileReference.java 2001/11/29 03:41:26 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/FileReference.java,v 1.1 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.1 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/FileReference.java,v 1.2 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.2 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -75,7 +75,7 @@ * information can be used to retrieve the file as a resource * or to retrieve a request dispatcher, etc.. * - * @version $Revision: 1.1 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.2 $, $Date: 2001/11/29 03:41:26 $ * @author Paul Speed */ public class FileReference { 1.5 +4 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ResponseIncludeWrapper.java Index: ResponseIncludeWrapper.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ResponseIncludeWrapper.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- ResponseIncludeWrapper.java 2001/10/26 19:35:23 1.4 +++ ResponseIncludeWrapper.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * ResponseIncludeWrapper.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ResponseIncludeWrapper.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ResponseIncludeWrapper.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -74,7 +74,7 @@ * A HttpServletResponseWrapper, used from <code>SsiInclude</code> * * @author Bip Thelin - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ */ public final class ResponseIncludeWrapper extends HttpServletResponseWrapper { 1.4 +4 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ServletOutputStreamWrapper.java Index: ServletOutputStreamWrapper.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ServletOutputStreamWrapper.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- ServletOutputStreamWrapper.java 2001/10/26 19:35:23 1.3 +++ ServletOutputStreamWrapper.java 2001/11/29 03:41:26 1.4 @@ -1,8 +1,8 @@ /* * ServletOutputStreamWrapper.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ServletOutputStreamWrapper.java,v 1.3 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.3 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ServletOutputStreamWrapper.java,v 1.4 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.4 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -74,7 +74,7 @@ * from within <code>SsiInclude</code> * * @author Bip Thelin - * @version $Revision: 1.3 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.4 $, $Date: 2001/11/29 03:41:26 $ * @see ServletOutputStream */ public final class ServletOutputStreamWrapper 1.4 +10 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommand.java Index: SsiCommand.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommand.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- SsiCommand.java 2001/10/26 19:35:23 1.3 +++ SsiCommand.java 2001/11/29 03:41:26 1.4 @@ -1,8 +1,8 @@ /* * SsiCommand.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommand.java,v 1.3 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.3 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommand.java,v 1.4 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.4 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -72,7 +72,7 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.3 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.4 $, $Date: 2001/11/29 03:41:26 $ */ public interface SsiCommand { @@ -96,4 +96,10 @@ throws IOException, SsiCommandException; + /** + * Returns true if the command should always be executed + * even if output is disabled. For example, all conditional + * commands should be run when output is disabled. + */ + public boolean alwaysExecute(); } 1.2 +4 -4 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommandException.java Index: SsiCommandException.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommandException.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SsiCommandException.java 2001/10/26 19:35:23 1.1 +++ SsiCommandException.java 2001/11/29 03:41:26 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommandException.java,v 1.1 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.1 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiCommandException.java,v 1.2 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.2 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -67,7 +67,7 @@ * Exception thrown by SsiCommands if they have problems during * execution. * - * @version $Revision: 1.1 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.2 $, $Date: 2001/11/29 03:41:26 $ * @author Paul Speed */ public class SsiCommandException extends Exception { 1.5 +5 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConfig.java Index: SsiConfig.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConfig.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SsiConfig.java 2001/10/26 19:35:23 1.4 +++ SsiConfig.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * SsiConfig.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConfig.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConfig.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -74,9 +74,9 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ */ -public final class SsiConfig implements SsiCommand { +public final class SsiConfig extends AbstractSsiCommand { /** * Variable to hold the patterns for translation 1.2 +17 -11 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiDispatcher.java Index: SsiDispatcher.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiDispatcher.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SsiDispatcher.java 2001/10/26 19:35:23 1.1 +++ SsiDispatcher.java 2001/11/29 03:41:26 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiDispatcher.java,v 1.1 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.1 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiDispatcher.java,v 1.2 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.2 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -73,7 +73,7 @@ * each SsiInokerServlet instance will have its own SsiDispatcher * and can therefore configure certain context-global settings. * - * @version $Revision: 1.1 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.2 $, $Date: 2001/11/29 03:41:26 $ * @author Paul Speed */ public class SsiDispatcher { @@ -101,22 +101,22 @@ ssiCommands.put("flastmod", new SsiFlastmod()); ssiCommands.put("exec", new SsiExec()); ssiCommands.put("set", new SsiSet()); + + SsiConditional cond = new SsiConditional(); + ssiCommands.put("if", cond); + ssiCommands.put("elif", cond); + ssiCommands.put("else", cond); + ssiCommands.put("endif", cond); } /** * Set to true to ignore unknown commands. */ - public void setIgnoreUnsupportedDirective(boolean flag) { + public void setIgnoreUnsupportedDirective( boolean flag ) { this.ignoreUnsupportedDirective = flag; } /** - * Set to true to consider the webapp as root. - public void setIsVirtualWebappRelative(boolean flag) { - this.isVirtualWebappRelative = flag; - } - - /** * Returns true if the dispatcher ignores unknown commands. */ public boolean ignoreUnsupportedDirective() { @@ -142,6 +142,7 @@ SsiEnvironment ssiEnv, ServletOutputStream out ) throws IOException { + // Lookup the command SsiCommand cmd = (SsiCommand)ssiCommands.get(cmdName); if (cmd == null) { @@ -151,6 +152,11 @@ } try { + // If output is disabled then only run the command if + // it should always be run + if (ssiEnv.isOutputDisabled() && !cmd.alwaysExecute()) + return; + // Run the command cmd.execute( cmdName, argNames, argVals, ssiEnv, out ); } catch (SsiCommandException e) { 1.4 +19 -10 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEcho.java Index: SsiEcho.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEcho.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- SsiEcho.java 2001/10/26 19:35:23 1.3 +++ SsiEcho.java 2001/11/29 03:41:26 1.4 @@ -1,8 +1,8 @@ /* * SsiEcho.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEcho.java,v 1.3 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.3 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEcho.java,v 1.4 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.4 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -72,9 +72,9 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.3 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.4 $, $Date: 2001/11/29 03:41:26 $ */ -public final class SsiEcho implements SsiCommand { +public final class SsiEcho extends AbstractSsiCommand { /** * Runs this command using the specified parameters. @@ -95,11 +95,20 @@ ServletOutputStream out ) throws IOException, SsiCommandException { - if (!"var".equals(argNames[0])) - throw new SsiCommandException( "Unknown parameter:" + argNames[0] ); + if (argNames.length == 0) + throw new SsiCommandException( "No var specified." ); - String val = ssiEnv.getVariable(argVals[0]); - - out.print( (val==null)?"(none)":val ); + for (int i = 0; i < argNames.length; i++ ) { + String name = argNames[i]; + if ("encoding".equals(name)) { + // silently ignore for forward compatability + } else if ("var".equals(name)) { + // Write each var that we find + String val = ssiEnv.getVariable(argVals[i]); + out.print( (val==null)?"(none)":val ); + } else { + throw new SsiCommandException( "Unknown parameter:" + name ); + } + } } } 1.2 +29 -16 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEnvironment.java Index: SsiEnvironment.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEnvironment.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SsiEnvironment.java 2001/10/26 19:35:23 1.1 +++ SsiEnvironment.java 2001/11/29 03:41:26 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEnvironment.java,v 1.1 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.1 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiEnvironment.java,v 1.2 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.2 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -87,7 +87,7 @@ * nested environment would not be shared. In any case, * createEnvironmentForRequest() takes care of these details. * - * @version $Revision: 1.1 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.2 $, $Date: 2001/11/29 03:41:26 $ * @author Paul Speed */ public class SsiEnvironment { @@ -117,6 +117,12 @@ private Hashtable ssiConfig; /** + * A place where commands can stick state information specific + * to this environment. + */ + private Hashtable commandVars = new Hashtable(7); + + /** * The ServletContext associated with this environment. */ private ServletContext servletContext; @@ -159,18 +165,6 @@ private boolean disableOutput; /** - * Used to track the number if "if" directives that have been - * encountered without yet seeing an "endif". - */ - private int conditionalCount = 0; - - /** - * Used to track the number of nested conditional branches that - * have been taken. - */ - private int branchCount = 0; - - /** * Creates a new SsiEnvironment instance for the specified request. * This method will create a new or nested instance as appropriate. * @@ -396,6 +390,25 @@ if (parent != null) return parent.getConfiguration(key); return (String)ssiConfig.get( key ); + } + + /** + * Sets the specified command variable. + */ + public void setCommandVariable( String key, Object value ) { + commandVars.put( key, value ); + } + + /** + * Returns the specified command variable. Command variables + * can be used by commands to store state information that needs + * to be associated with a specific request and used across + * multiple command executions. Note: it may be better to + * change get/setConfiguration to take Object values and use + * it instead. + */ + public Object getCommandVariable( String key ) { + return commandVars.get( key ); } /** 1.5 +8 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiExec.java Index: SsiExec.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiExec.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SsiExec.java 2001/10/26 19:35:23 1.4 +++ SsiExec.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * SsiExec.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiExec.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiExec.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -80,10 +80,10 @@ * @author Bip Thelin * @author Amy Roh * @author Paul Speed - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ * */ -public final class SsiExec implements SsiCommand { +public final class SsiExec extends AbstractSsiCommand { /** * Runs this command using the specified parameters. @@ -104,6 +104,9 @@ ServletOutputStream out ) throws IOException, SsiCommandException { + + if (argNames.length == 0) + throw new SsiCommandException( "No executable specified." ); if ("cgi".equals(argNames[0])) { String path = getCGIPath(argVals[0], ssiEnv.getContextPath()); 1.5 +8 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFlastmod.java Index: SsiFlastmod.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFlastmod.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SsiFlastmod.java 2001/10/26 19:35:23 1.4 +++ SsiFlastmod.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * SsiFlastmod.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFlastmod.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFlastmod.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -77,9 +77,9 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ */ -public final class SsiFlastmod implements SsiCommand { +public final class SsiFlastmod extends AbstractSsiCommand { /** * Runs this command using the specified parameters. @@ -101,6 +101,9 @@ throws IOException, SsiCommandException { FileReference ref = null; + + if (argNames.length == 0) + throw new SsiCommandException( "No path specified." ); String value = ssiEnv.substituteVariables( argVals[0] ); 1.5 +8 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFsize.java Index: SsiFsize.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFsize.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SsiFsize.java 2001/10/26 19:35:23 1.4 +++ SsiFsize.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * SsiFsize.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFsize.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiFsize.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -75,9 +75,9 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ */ -public final class SsiFsize implements SsiCommand { +public final class SsiFsize extends AbstractSsiCommand { /** * Runs this command using the specified parameters. @@ -99,6 +99,9 @@ throws IOException, SsiCommandException { FileReference ref = null; + + if (argNames.length == 0) + throw new SsiCommandException( "No path specified." ); String value = ssiEnv.substituteVariables( argVals[0] ); 1.5 +8 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiInclude.java Index: SsiInclude.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiInclude.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SsiInclude.java 2001/10/26 19:35:23 1.4 +++ SsiInclude.java 2001/11/29 03:41:26 1.5 @@ -1,8 +1,8 @@ /* * SsiInclude.java - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiInclude.java,v 1.4 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.4 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiInclude.java,v 1.5 2001/11/29 03:41:26 amyroh Exp $ + * $Revision: 1.5 $ + * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * @@ -76,9 +76,9 @@ * * @author Bip Thelin * @author Paul Speed - * @version $Revision: 1.4 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.5 $, $Date: 2001/11/29 03:41:26 $ */ -public final class SsiInclude implements SsiCommand { +public final class SsiInclude extends AbstractSsiCommand { /** * Runs this command using the specified parameters. @@ -99,6 +99,9 @@ ServletOutputStream out ) throws IOException, SsiCommandException { + if (argNames.length == 0) + throw new SsiCommandException( "No path specified." ); + FileReference ref = null; String value = ssiEnv.substituteVariables( argVals[0] ); 1.2 +5 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiSet.java Index: SsiSet.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiSet.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SsiSet.java 2001/10/26 19:35:23 1.1 +++ SsiSet.java 2001/11/29 03:41:27 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiSet.java,v 1.1 2001/10/26 19:35:23 bip Exp $ - * $Revision: 1.1 $ - * $Date: 2001/10/26 19:35:23 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiSet.java,v 1.2 2001/11/29 03:41:27 amyroh Exp $ + * $Revision: 1.2 $ + * $Date: 2001/11/29 03:41:27 $ * * ==================================================================== * @@ -68,10 +68,10 @@ /** * SSI command to set a server variable in the SsiEnvironment. * - * @version $Revision: 1.1 $, $Date: 2001/10/26 19:35:23 $ + * @version $Revision: 1.2 $, $Date: 2001/11/29 03:41:27 $ * @author Paul Speed */ -public final class SsiSet implements SsiCommand { +public final class SsiSet extends AbstractSsiCommand { /** * Runs this command using the specified parameters. 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/AbstractSsiCommand.java Index: AbstractSsiCommand.java =================================================================== /* * AbstractSsiCommand.java * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/AbstractSsiCommand.java,v 1.1 2001/11/29 03:41:26 amyroh Exp $ * $Revision: 1.1 $ * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.util.ssi; import java.io.IOException; import javax.servlet.ServletOutputStream; /** * Default abstract implemention of the SsiCommand interface. * * @author Paul Speed * @version $Revision: 1.1 $ */ public abstract class AbstractSsiCommand implements SsiCommand { /** * Runs this command using the specified parameters. * * @param cmdName The name that was used to lookup this * command instance. * @param argNames String array containing the parameter * names for the command. * @param argVals String array containing the paramater * values for the command. * @param ssiEnv The environment to use for command * execution. * @param out A convenient place for commands to * write their output. */ public abstract void execute( String cmdName, String[] argNames, String[] argVals, SsiEnvironment ssiEnv, ServletOutputStream out ) throws IOException, SsiCommandException; /** * Returns true if the command should always be executed * even if output is disabled. Default implementation * returns false. */ public boolean alwaysExecute() { return false; } } 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ExpressionParseTree.java Index: ExpressionParseTree.java =================================================================== /* * ExpressionParseTree.java * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ExpressionParseTree.java,v 1.1 2001/11/29 03:41:26 amyroh Exp $ * $Revision: 1.1 $ * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.util.ssi; import java.util.LinkedList; import java.util.List; import java.text.ParseException; /** * Represents a parsed expression. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class ExpressionParseTree { /** * Contains the current set of completed nodes. This * is a workspace for the parser. */ private LinkedList nodeStack = new LinkedList(); /** * Contains operator nodes that don't yet have values. * This is a workspace for the parser. */ private LinkedList oppStack = new LinkedList(); /** * The root node after the expression has been parsed. */ private Node root; /** * The SsiEnvironment to use when evaluating the expressions. */ private SsiEnvironment ssiEnv; /** * Creates a new parse tree for the specified expression. */ public ExpressionParseTree( String expr, SsiEnvironment ssiEnv ) throws ParseException { this.ssiEnv = ssiEnv; parseExpression( expr ); } /** * Evaluates the tree and returns true or false. The specified * SsiEnvironment is used to resolve variable references. */ public boolean evaluateTree() { return root.evaluate(); } /** * Pushes a new operator onto the opp stack, resolving existing * opps as needed. */ private void pushOpp( OppNode node ) { // If node is null then it's just a group marker if( node == null ) { oppStack.add( 0, node ); return; } while (true) { if (oppStack.size() == 0) break; OppNode top = (OppNode)oppStack.get(0); // If the top is a spacer then don't pop // anything if (top == null) break; // If the top node has a lower precedence then // let it stay if (top.getPrecedence() < node.getPrecedence()) break; // Remove the top node oppStack.remove(0); // Let it fill its branches top.popValues( nodeStack ); // Stick it on the resolved node stack nodeStack.add( 0, top ); } // Add the new node to the opp stack oppStack.add( 0, node ); } /** * Resolves all pending opp nodes on the stack until the * next group marker is reached. */ private void resolveGroup() { OppNode top = null; while ((top=(OppNode)oppStack.remove(0)) != null ) { // Let it fill its branches top.popValues( nodeStack ); // Stick it on the resolved node stack nodeStack.add( 0, top ); } } /** * Parses the specified expression into a tree of * parse nodes. */ private void parseExpression( String expr ) throws ParseException { StringNode currStringNode = null; // We cheat a little and start an artificial // group right away. It makes finishing easier. pushOpp( null ); ExpressionTokenizer et = new ExpressionTokenizer(expr); while (et.hasMoreTokens()) { int token = et.nextToken(); if (token != ExpressionTokenizer.TOKEN_STRING) currStringNode = null; switch (token) { case ExpressionTokenizer.TOKEN_STRING: if (currStringNode == null) { currStringNode = new StringNode( et.getTokenValue() ); nodeStack.add( 0, currStringNode ); } else { // Add to the existing currStringNode.value.append( " " ); currStringNode.value.append( et.getTokenValue() ); } break; case ExpressionTokenizer.TOKEN_AND: pushOpp( new AndNode() ); break; case ExpressionTokenizer.TOKEN_OR: pushOpp( new OrNode() ); break; case ExpressionTokenizer.TOKEN_NOT: pushOpp( new NotNode() ); break; case ExpressionTokenizer.TOKEN_EQ: pushOpp( new EqualNode() ); break; case ExpressionTokenizer.TOKEN_NOT_EQ: pushOpp( new NotNode() ); // Sneak the regular node in. The NOT will // be resolved when the next opp comes along. oppStack.add( 0, new EqualNode() ); break; case ExpressionTokenizer.TOKEN_RBRACE: // Closeout the current group resolveGroup(); break; case ExpressionTokenizer.TOKEN_LBRACE: // Push a group marker pushOpp( null ); break; case ExpressionTokenizer.TOKEN_GE: pushOpp( new NotNode() ); // Similar stategy to NOT_EQ above, except this // is NOT less than oppStack.add( 0, new LessThanNode() ); break; case ExpressionTokenizer.TOKEN_LE: pushOpp( new NotNode() ); // Similar stategy to NOT_EQ above, except this // is NOT greater than oppStack.add( 0, new GreaterThanNode() ); break; case ExpressionTokenizer.TOKEN_GT: pushOpp( new GreaterThanNode() ); break; case ExpressionTokenizer.TOKEN_LT: pushOpp( new LessThanNode() ); break; case ExpressionTokenizer.TOKEN_END: break; } } // Finish off the rest of the opps resolveGroup(); if (nodeStack.size() == 0) { throw new ParseException( "No nodes created.", et.getIndex() ); } if (nodeStack.size() > 1) { throw new ParseException( "Extra nodes created.", et.getIndex() ); } if (oppStack.size() != 0) { throw new ParseException( "Unused opp nodes exist.", et.getIndex() ); } root = (Node)nodeStack.get(0); } /** * A node in the expression parse tree. */ private abstract class Node { /** * Return true if the node evaluates to true. */ public abstract boolean evaluate(); } /** * A node the represents a String value */ private class StringNode extends Node { StringBuffer value; String resolved = null; public StringNode( String value ) { this.value = new StringBuffer(value); } /** * Resolves any variable references and returns the * value string. */ public String getValue() { if (resolved == null) resolved = ssiEnv.substituteVariables( value.toString() ) ; return resolved; } /** * Returns true if the string is not empty. */ public boolean evaluate() { return !(getValue().length() == 0); } public String toString() { return value.toString(); } } private static final int PRECEDENCE_NOT = 5; private static final int PRECEDENCE_COMPARE = 4; private static final int PRECEDENCE_LOGICAL = 1; /** * A node implementation that represents an operation. */ private abstract class OppNode extends Node { /** * The left branch. */ Node left; /** * The right branch. */ Node right; /** * Returns a preference level suitable for comparison to * other OppNode preference levels. */ public abstract int getPrecedence(); /** * Lets the node pop its own branch nodes off the front of * the specified list. The default pulls two. */ public void popValues( List values ) { right = (Node)values.remove(0); left = (Node)values.remove(0); } } private final class NotNode extends OppNode { public boolean evaluate() { return !left.evaluate(); } public int getPrecedence() { return PRECEDENCE_NOT; } /** * Overridden to pop only one value. */ public void popValues( List values ) { left = (Node)values.remove(0); } public String toString() { return left + " NOT"; } } private final class AndNode extends OppNode { public boolean evaluate() { if (!left.evaluate()) // Short circuit return false; return right.evaluate(); } public int getPrecedence() { return PRECEDENCE_LOGICAL; } public String toString() { return left + " " + right + " AND"; } } private final class OrNode extends OppNode { public boolean evaluate() { if (left.evaluate()) // Short circuit return true; return right.evaluate(); } public int getPrecedence() { return PRECEDENCE_LOGICAL; } public String toString() { return left + " " + right + " OR"; } } private abstract class CompareNode extends OppNode { protected int compareBranches() { String val1 = ((StringNode)left).getValue(); String val2 = ((StringNode)right).getValue(); return val1.compareTo(val2); } } private final class EqualNode extends CompareNode { public boolean evaluate() { return (compareBranches() == 0); } public int getPrecedence() { return PRECEDENCE_COMPARE; } public String toString() { return left + " " + right + " EQ"; } } private final class GreaterThanNode extends CompareNode { public boolean evaluate() { return (compareBranches() > 0); } public int getPrecedence() { return PRECEDENCE_COMPARE; } public String toString() { return left + " " + right + " GT"; } } private final class LessThanNode extends CompareNode { public boolean evaluate() { return (compareBranches() < 0); } public int getPrecedence() { return PRECEDENCE_COMPARE; } public String toString() { return left + " " + right + " LT"; } } } 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ExpressionTokenizer.java Index: ExpressionTokenizer.java =================================================================== /* * ExpressionTokenizer.java * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/ExpressionTokenizer.java,v 1.1 2001/11/29 03:41:26 amyroh Exp $ * $Revision: 1.1 $ * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.util.ssi; /** * Parses an expression string to return the individual tokens. * This is patterned similar to the StreamTokenizer in the JDK * but customized for SSI conditional expression parsing. * * @version $Revision: 1.1 $ * @author Paul Speed */ public class ExpressionTokenizer { public static final int TOKEN_STRING = 0; public static final int TOKEN_AND = 1; public static final int TOKEN_OR = 2; public static final int TOKEN_NOT = 3; public static final int TOKEN_EQ = 4; public static final int TOKEN_NOT_EQ = 5; public static final int TOKEN_RBRACE = 6; public static final int TOKEN_LBRACE = 7; public static final int TOKEN_GE = 8; public static final int TOKEN_LE = 9; public static final int TOKEN_GT = 10; public static final int TOKEN_LT = 11; public static final int TOKEN_END = 12; private char[] expr; private int tokenType = TOKEN_STRING; private String tokenVal = null; private int index; private int length; /** * Creates a new parser for the specified expression. */ public ExpressionTokenizer( String expr ) { this.expr = expr.trim().toCharArray(); this.length = this.expr.length; } /** * Returns true if there are more tokens. */ public boolean hasMoreTokens() { return index < length; } /** * Returns the current index for error reporting purposes. */ public int getIndex() { return index; } /** * Returns the next token type and initializes any * state variables accordingly. */ public int nextToken() { // Skip any leading white space while (index<length && Character.isWhitespace(expr[index])) index++; // Clear the current token val tokenVal = null; if (index == length) return TOKEN_END; // End of string int start = index; char currentChar = expr[index]; char nextChar = (char)0; index++; if (index < length) nextChar = expr[index]; // Check for a known token start switch (currentChar) { case '(': return TOKEN_LBRACE; case ')': return TOKEN_RBRACE; case '=': return TOKEN_EQ; case '!': if (nextChar == '=') { index++; return TOKEN_NOT_EQ; } else { return TOKEN_NOT; } case '|': if (nextChar == '|') { index++; return TOKEN_OR; } break; case '&': if (nextChar == '&') { index++; return TOKEN_AND; } break; case '>': if (nextChar == '=') { index++; return TOKEN_GE; // Greater than or equal } else { return TOKEN_GT; // Greater than } case '<': if (nextChar == '=') { index++; return TOKEN_LE; // Less than or equal } else { return TOKEN_LT; // Less than } default: // Otherwise it's a string break; } int end = index; // If it's a quoted string then end is the next unescaped quote if (currentChar == '"' || currentChar == '\'') { char endChar = currentChar; boolean escaped = false; start++; for ( ; index < length; index++) { if (expr[index] == '\\' && !escaped) { escaped = true; continue; } if (expr[index] == endChar && !escaped) break; escaped = false; } end = index; index++; // Skip the end quote } else { // End is the next whitespace character for ( ; index < length; index++) { if (Character.isWhitespace(expr[index])) break; } end = index; } // Extract the string from the array this.tokenVal = new String( expr, start, end - start ); return TOKEN_STRING; } /** * Returns the String value of the token if it was type * TOKEN_STRING. Otherwise null is returned. */ public String getTokenValue() { return tokenVal; } } 1.1 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConditional.java Index: SsiConditional.java =================================================================== /* * SsiConditional.java * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/ssi/SsiConditional.java,v 1.1 2001/11/29 03:41:26 amyroh Exp $ * $Revision: 1.1 $ * $Date: 2001/11/29 03:41:26 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.util.ssi; import java.text.ParseException; import java.util.LinkedList; import java.util.List; import javax.servlet.ServletOutputStream; /** * SSI command that handles all conditional directives. * * @version $Revision: 1.1 $ * @author Paul Speed */ public final class SsiConditional extends AbstractSsiCommand { /** * Returns true, conditional directives should always * be executed. */ public boolean alwaysExecute() { return true; } /** * Runs this command using the specified parameters. * * @param cmdName The name that was used to lookup this * command instance. * @param argNames String array containing the parameter * names for the command. * @param argVals String array containing the paramater * values for the command. * @param ssiEnv The environment to use for command * execution. * @param out A convenient place for commands to * write their output. */ public void execute( String cmdName, String[] argNames, String[] argVals, SsiEnvironment ssiEnv, ServletOutputStream out ) throws SsiCommandException { // Retrieve the current state information ConditionState state = getState( ssiEnv ); boolean disableOutput = ssiEnv.isOutputDisabled(); if ("if".equals( cmdName )) { // Do nothing if we are nested in a false branch // except count it if (disableOutput) { state.nestingCount++; return; } state.nestingCount = 0; // Evaluate the expression if (evaluateArguments(argNames, argVals, ssiEnv)) { // No more branches can be taken for this if block state.branchTaken = true; } else { // Do not process this branch ssiEnv.setOutputDisabled(true); state.branchTaken = false; } } else if ("elif".equals( cmdName )) { // No need to even execute if we are nested in // a false branch if (state.nestingCount > 0) return; // If a branch was already taken in this if block // then disable output and return if (state.branchTaken) { ssiEnv.setOutputDisabled(true); return; } // Evaluate the expression if (evaluateArguments(argNames, argVals, ssiEnv)) { // Turn back on output and mark the branch ssiEnv.setOutputDisabled(false); state.branchTaken = true; } else { // Do not process this branch ssiEnv.setOutputDisabled(true); state.branchTaken = false; } } else if ("else".equals( cmdName )) { // No need to even execute if we are nested in // a false branch if (state.nestingCount > 0) return; // If we've already taken another branch then // disable output otherwise enable it. ssiEnv.setOutputDisabled( state.branchTaken ); // And in any case, it's safe to say a branch // has been taken. state.branchTaken = true; } else if ("endif".equals( cmdName )) { // If we are nested inside a false branch then pop out // one level on the nesting count if (state.nestingCount > 0) { state.nestingCount--; return; } // Turn output back on ssiEnv.setOutputDisabled(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 SsiCommandException( "Not a conditional command:" + cmdName ); } } /** * Returns the current ConditionalState as retrieved from * the specified SsiEnvironment. If no state exists, one * will be created. */ private ConditionState getState( SsiEnvironment ssiEnv ) { ConditionState state = null; state = (ConditionState)ssiEnv.getCommandVariable( "conditionState" ); if (state == null) { state = new ConditionState(); ssiEnv.setCommandVariable( "conditionState", state ); } return state; } /** * Retrieves the expression from the specified arguments * and peforms the necessary evaluation steps. */ private boolean evaluateArguments( String[] names, String[] vals, SsiEnvironment ssiEnv ) throws SsiCommandException { String expr = getExpression( names, vals ); if (expr == null) throw new SsiCommandException( "No expression specified." ); try { ExpressionParseTree tree = new ExpressionParseTree( expr, ssiEnv ); return tree.evaluateTree(); } catch (ParseException e) { throw new SsiCommandException( "Error parsing expression." ); } } /** * Returns the "expr" if the arg name is appropriate, otherwise * returns null. */ private String getExpression( String[] argNames, String[] argVals ) { if ("expr".equals(argNames[0])) return argVals[0]; return null; } /** * Stored as a SsiEnvironment configuration variable, this * class contains the state information necessary to process * the nested if's and set the disableOutput variable * appropriately. */ private class ConditionState { /** * Set to true if the current conditional has already been * completed, i.e.: a branch was taken. */ boolean branchTaken = false; /** * Counts the number of nested false branches. */ int nestingCount = 0; } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>