You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by sh...@locus.apache.org on 2000/02/07 08:51:23 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/jasper/runtime JspLoader.java JspServlet.java

shemnon     00/02/06 23:51:22

  Modified:    src/share/org/apache/jasper/compiler Compiler.java
                        JspCompiler.java
               .        build.xml
               src/share/org/apache/jasper/resources messages.properties
               src/share/org/apache/jasper/runtime JspLoader.java
                        JspServlet.java
  Added:       src/share/org/apache/jasper JspC.java
                        CommandLineContext.java
               src/share/org/apache/jasper/compiler
                        CommandLineCompiler.java
  Log:
  jspc -- a command line tool to compile jsp files into java files.
    Most of the files are additons and minor alterations.  However
    management of the freshness of jsp pages was moved from JspLoader
    to JspServlet so that JspLoader could be used outside of the context
    of a runtime environment.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat/src/share/org/apache/jasper/JspC.java
  
  Index: JspC.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/JspC.java,v 1.1 2000/02/07 07:51:17 shemnon Exp $
   * $Revision: 1.1 $
   * $Date: 2000/02/07 07:51:17 $
   *
   * ====================================================================
   * 
   * 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 apache@apache.org.
   *
   * 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/>.
   *
   */ 
  
  package org.apache.jasper;
  
  import java.io.*;
  import org.apache.jasper.compiler.JspReader;
  import org.apache.jasper.compiler.ServletWriter;
  import org.apache.jasper.compiler.TagLibraries;
  import org.apache.jasper.compiler.Compiler;
  import org.apache.jasper.compiler.CommandLineCompiler;
  
  import org.apache.jasper.runtime.JspLoader;
  
  /**
   * Shell for the jspc compiler.  Handles all options associated with the 
   * command line and creates compilation contexts which it then compiles
   * according to the specified options.
   *@author Danno Ferrin
   */
  public class JspC implements Options { //, JspCompilationContext {
  
      public static final String DEFAULT_IE_CLASS_ID = 
              "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
      
      public static final String SWITCH_VERBOSE = "-v";
      public static final String SWITCH_QUIET = "-q";
      public static final String SWITCH_OUTPUT_DIR = "-d";
      public static final String SWITCH_IE_CLASS_ID = "-ieplugin";
      public static final String SWITCH_PACKAGE_NAME = "-p";
      public static final String SWITCH_CLASS_NAME = "-c";
      public static final String SWITCH_FULL_STOP = "--";
      public static final String SWITCH_URI_BASE = "-uribase";
      public static final String SWITCH_URI_ROOT = "-uriroot";
  
      // future direction
      //public static final String SWITCH_XML_OUTPUT = "-xml";
    
      
      boolean largeFile = false;
  
      int jspVerbosityLevel = Constants.MED_VERBOSITY;
  
      File scratchDir;
  
      String ieClassId = DEFAULT_IE_CLASS_ID;
  
      //String classPath;
      
      String targetPackage;
      
      String targetClassName;
  
      String uriBase;
  
      String uriRoot;
  
      //JspLoader loader;
  
  
      public boolean getKeepGenerated() {
          // isn't this why we are running jspc?
          return true;
      }
      
      public boolean getLargeFile() {
          return largeFile;
      }
      
      public boolean getSendErrorToClient() {
          // implied send to System.err
          return true;
      }
   
      public String getIeClassId() {
          return ieClassId;
      }
      
      public int getJspVerbosityLevel() {
          return jspVerbosityLevel;
      }
  
      public File getScratchDir() {
          return scratchDir;
      }
  
      //public String getClassPath() {
      //    return classpath;
      //}
  
      public Class getJspCompilerPlugin() {
         // we don't compile, so this is meanlingless
          return null;
      }
  
      public String getJspCompilerPath() {
         // we don't compile, so this is meanlingless
          return null;
      }
  
      public String getClassPath() {
          return System.getProperty("java.class.path");
      }
      
      int argPos;
      // value set by beutifully obsfucscated java
      boolean fullstop = false;
      String args[];
  
      private void pushBackArg() {
          if (!fullstop) {
              argPos--;
          };
      };
  
      private String nextArg() {
          if ((argPos >= args.length)
              || (fullstop = SWITCH_FULL_STOP.equals(args[argPos]))) {
              return null;
          } else {
              return args[argPos++];
          }
      };
          
      private String nextFile() {
          if (fullstop) argPos++;
          if (argPos >= args.length) {
              return null;
          } else {
              return args[argPos++];
          }
      };
  
      public JspC(String[] arg, PrintStream log) {
          args = arg;
          String tok;
  
          while ((tok = nextArg()) != null) {
              if (tok.equals(SWITCH_QUIET)) {
                  jspVerbosityLevel = Constants.WARNING;
              } else if (tok.equals(SWITCH_VERBOSE)) {
                  jspVerbosityLevel = Constants.HIGH_VERBOSITY;
              } else if (tok.startsWith(SWITCH_VERBOSE)) {
                  try {
                      jspVerbosityLevel = Integer.parseInt(
                              tok.substring(SWITCH_VERBOSE.length()));
                  } catch (NumberFormatException nfe) {
                      log.println(
                          "Verbosity level " 
                          + tok.substring(SWITCH_VERBOSE.length()) 
                          + " is not valid.  Option ignored.");
                  }
              } else if (tok.equals(SWITCH_OUTPUT_DIR)) {
                  tok = nextArg();
                  if (tok != null) {
                      scratchDir = new File(tok);
                  } else {
                      // either an in-java call with an explicit null
                      // or a "-d --" sequence should cause this,
                      // which would mean default handling
                      /* no-op */
                      scratchDir = null;
                  }
              } else if (tok.equals(SWITCH_PACKAGE_NAME)) {
                  targetPackage = nextArg();
              } else if (tok.equals(SWITCH_CLASS_NAME)) {
                  targetClassName = nextArg();
              } else if (tok.equals(SWITCH_URI_BASE)) {
                  uriBase = nextArg();
              } else if (tok.equals(SWITCH_URI_ROOT)) {
                  uriRoot = nextArg();
              } else {
                  pushBackArg();
                  // Not a recognized Option?  Start treting them as JSP Pages
                  break;
              }
          }
      };
      
      public void parseFiles(PrintStream log)  throws JasperException {
          if (scratchDir == null) {
              String temp = System.getProperty("java.io.tempdir");
              if (temp == null) {
                  temp = "";
              }
              scratchDir = new File(temp);
          }
          String file = nextFile();
          while (file != null) {
              try {
                  JspLoader loader =
                          new JspLoader(getClass().getClassLoader(), this);
                  CommandLineContext clctxt = new CommandLineContext(
                          loader, getClassPath(), file, uriBase, uriRoot, false,
                          this);
                  loader.addJar(clctxt.getRealPath("/WEB-INF/classes"));
                  CommandLineCompiler clc = new CommandLineCompiler(clctxt);
                  
                  clc.compile();
              } catch (JasperException je) {
                  je.printStackTrace(System.err);
                  System.out.print("error:");
                  System.out.println(je.getMessage());
              } catch (Exception e) {
                  System.out.print("ERROR:");
                  System.out.println(e.toString());
              };
              targetClassName = null;
              file = nextFile();
          }
      };
  
      public static void main(String arg[]) {
          if (arg.length == 0) {
             System.out.println(Constants.getString("jspc.usage"));
          } else {
              try {
                  JspC jspc = new JspC(arg, System.out);
                  jspc.parseFiles(System.out);
              } catch (JasperException je) {
                  System.err.print("error:");
                  System.err.println(je.getMessage());
              }
          }
      };
  
  }
  
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/jasper/CommandLineContext.java
  
  Index: CommandLineContext.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/CommandLineContext.java,v 1.1 2000/02/07 07:51:17 shemnon Exp $
   * $Revision: 1.1 $
   * $Date: 2000/02/07 07:51:17 $
   *
   * ====================================================================
   * 
   * 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 apache@apache.org.
   *
   * 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/>.
   *
   */ 
  
  
  
  
  
  package org.apache.jasper;
  
  import java.io.*;
  
  import org.apache.jasper.compiler.JspReader;
  import org.apache.jasper.compiler.ServletWriter;
  import org.apache.jasper.compiler.TagLibraries;
  import org.apache.jasper.compiler.CommandLineCompiler;
  import org.apache.jasper.compiler.Compiler;
  
  import org.apache.jasper.runtime.JspLoader;
  
  /**
   * Holds data used on a per-page compilation context that would otherwise spill
   * over to other pages being compiled.  Things like the taglib classloaders
   * and directives.
   *
   *@author Danno Ferrin
   */
  public class CommandLineContext implements JspCompilationContext {
  
      String classPath;
      JspReader reader;
      ServletWriter writer;
      JspLoader loader;
      boolean errPage;
      String jspFile;
      String servletClassName;
      String servletPackageName;
      String servletJavaFileName;
      String contentType;
      Options options;
  
      String uriBase;
      File uriRoot;
  
      public CommandLineContext(JspLoader newLoader, String newClassPath,
                                String newJspFile, String newUriBase,
                                String newUriRoot, boolean newErrPage,
                                Options newOptions)
      throws JasperException
      {
          loader = newLoader;
          classPath = newClassPath;
          uriBase = newUriBase;
          String tUriRoot = newUriRoot;
          jspFile = newJspFile;
          errPage = newErrPage;
          options = newOptions;
  
          if (uriBase == null) {
              uriBase = "/";
          } else if (uriBase.charAt(0) != '/') {
              // strip the basde slash since it will be combined with the
              // uriBase to generate a file
              uriBase = "/" + uriBase;
          };
  
          if (uriBase.charAt(uriBase.length() - 1) != '/') {
              uriBase += '/';
          };
  
          if (tUriRoot == null) {
              uriRoot = new File("");
          } else {
              uriRoot = new File(tUriRoot);
              if (!uriRoot.exists() || !uriRoot.isDirectory()) {
                 System.out.println(uriRoot);
                 System.out.println(uriRoot.exists());
                 System.out.println(uriRoot.isDirectory());
                 System.out.println(uriRoot.getAbsolutePath());
                 throw new JasperException(
                          Constants.getString("jsp.error.jspc.uriroot_not_dir"));
              };
          };
      };
  
      /**
       * The classpath that is passed off to the Java compiler. 
       */
      public String getClassPath() {
          return classPath;
      };
      
      /**
       * Get the input reader for the JSP text. 
       */
      public JspReader getReader() {
          return reader;
      };
      
      /**
       * Where is the servlet being generated?
       */
      public ServletWriter getWriter() {
          return writer;
      };
      
      /**
       * What class loader to use for loading classes while compiling
       * this JSP? I don't think this is used right now -- akv. 
       */
      public JspLoader getClassLoader() {
          return loader;
      };
      
      /**
       * Are we processing something that has been declared as an
       * errorpage? 
       */
      public boolean isErrorPage() {
          return errPage;
      };
      
      /**
       * What is the scratch directory we are generating code into?
       * FIXME: In some places this is called scratchDir and in some
       * other places it is called outputDir.
       */
      public String getOutputDir() {
          return options.getScratchDir().toString();
      };
      
      /**
       * Path of the JSP URI. Note that this is not a file name. This is
       * the context rooted URI of the JSP file. 
       */
      public String getJspFile() {
          return jspFile;
      };
      
      /**
       * Just the class name (does not include package name) of the
       * generated class. 
       */
      public String getServletClassName() {
          return servletClassName;
      };
      
      /**
       * The package name into which the servlet class is generated. 
       */
      public String getServletPackageName() {
          return servletPackageName;
      };
  
      /**
       * Utility method to get the full class name from the package and
       * class name. 
       */
      public String getFullClassName() {
          String pkg = getServletPackageName();
          if (pkg != null) {
              pkg += ".";
          } else {
              pkg = "";
          };
          return pkg + getServletClassName();
     };
  
      /**
       * Full path name of the Java file into which the servlet is being
       * generated. 
       */
      public String getServletJavaFileName() {
          return servletJavaFileName;
      };
  
      /**
       * Are we keeping generated code around?
       */
      public boolean keepGenerated() {
          return options.getKeepGenerated();
      };
  
      /**
       * What's the content type of this JSP? Content type includes
       * content type and encoding. 
       */
      public String getContentType() {
          return contentType;
      };
  
      /**
       * Get hold of the Options object for this context. 
       */
      public Options getOptions() {
          return options;
      };
  
      public void setContentType(String contentType) {
          this.contentType = contentType;
      };
  
      public void setReader(JspReader reader) {
          this.reader = reader;
      };
      
      public void setWriter(ServletWriter writer) {
          this.writer = writer;
      };
      
      public void setServletClassName(String servletClassName) {
          this.servletClassName = servletClassName;
      };
      
      public void setServletPackageName(String servletPackageName) {
          this.servletPackageName = servletPackageName;
      };
      
      public void setServletJavaFileName(String servletJavaFileName) {
          this.servletJavaFileName = servletJavaFileName;
      };
      
      public void setErrorPage(boolean isErrPage) {
          errPage = isErrPage;
      };
  
      /**
       * Create a "Compiler" object based on some init param data. This
       * is not done yet. Right now we're just hardcoding the actual
       * compilers that are created. 
       */
      public Compiler createCompiler() throws JasperException {
          return new CommandLineCompiler(this);
      };
  
  
      /** 
       * Get the full value of a URI relative to this compilations context
       * uses current file as the base.
       */
      public String resolveRelativeUri(String uri) {
          if (uri.charAt(0) == '/') {
              return uri;
          } else {
              return uriBase + uri;
          };
      };
  
  
      /**
       * Gets a resource as a stream, relative to the meanings of this
       * context's implementation.
       *@returns a null if the resource cannot be found or represented 
       *         as an InputStream.
       */
      public java.io.InputStream getResourceAsStream(String res) {
          InputStream in;
          // fisrt try and get it from the URI
          try {
              in = new FileInputStream(getRealPath(res));
          } catch (IOException ioe) {
              in = null;
          };
          // next, try it as an absolute name
          if (in == null) try {
              in = new FileInputStream(res);
          } catch (IOException ioe) {
              in = null;
          };
          // that dind't work, last chance is to try the classloaders
          if (in == null) {
              in = loader.getResourceAsStream(res);
          };
          return in;
      };
  
  
      /** 
       * Gets the actual path of a URI relative to the context of
       * the compilation.
       */
      public String getRealPath(String path) {
          path = resolveRelativeUri(path);
          if (path.charAt(0) == '/') {
              path.substring(1);
          };
          File f = new File(uriRoot, path.replace('/', File.separatorChar));
          return f.getAbsolutePath();
      };
  
  }
  
  
  
  
  1.10      +11 -5     jakarta-tomcat/src/share/org/apache/jasper/compiler/Compiler.java
  
  Index: Compiler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/Compiler.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Compiler.java	2000/02/03 02:13:12	1.9
  +++ Compiler.java	2000/02/07 07:51:18	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/Compiler.java,v 1.9 2000/02/03 02:13:12 mandar Exp $
  - * $Revision: 1.9 $
  - * $Date: 2000/02/03 02:13:12 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/Compiler.java,v 1.10 2000/02/07 07:51:18 shemnon Exp $
  + * $Revision: 1.10 $
  + * $Date: 2000/02/07 07:51:18 $
    *
    * ====================================================================
    * 
  @@ -164,7 +164,7 @@
   
           ctxt.setReader(reader);
           ctxt.setWriter(writer);
  -        
  +
           ParseEventListener listener = new JspParseEventListener(ctxt);
           
           Parser p = new Parser(reader, listener);
  @@ -206,7 +206,13 @@
            * anything to the constructor which will be less. 
            */
           ByteArrayOutputStream out = new ByteArrayOutputStream (256);
  -    
  +
  +        // if no compiler was set we can kick out now
  +
  +        if (javac == null) {
  +            return true;
  +        }
  +
           /**
            * Configure the compiler object
            */
  
  
  
  1.6       +7 -1      jakarta-tomcat/src/share/org/apache/jasper/compiler/JspCompiler.java
  
  Index: JspCompiler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/JspCompiler.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- JspCompiler.java	2000/01/24 05:54:51	1.5
  +++ JspCompiler.java	2000/02/07 07:51:18	1.6
  @@ -64,7 +64,13 @@
   
   /**
    * JspCompiler is an implementation of Compiler with a funky code
  - * mangling and code generation scheme! 
  + * mangling and code generation scheme!
  + *
  + * The reason that it is both a sub-class of compiler and an implementation
  + * of mangler is because the isOutDated method that is overridden and the
  + * name mangulation both depend on the actual existance of other class and
  + * java files.  I.e. the value of a mangled name is a function of both the
  + * name to be mangled and also of the state of the scratchdir.
    *
    * @author Anil K. Vijendran
    */
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/jasper/compiler/CommandLineCompiler.java
  
  Index: CommandLineCompiler.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/CommandLineCompiler.java,v 1.1 2000/02/07 07:51:18 shemnon Exp $
   * $Revision: 1.1 $
   * $Date: 2000/02/07 07:51:18 $
   *
   * 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 apache@apache.org.
   *
   * 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/>.
   *
   */
  
  package org.apache.jasper.compiler;
  
  import java.io.File;
  
  import org.apache.jasper.Constants;
  import org.apache.jasper.JspCompilationContext;
  
  /**
   * Overrides some methods so that we get the desired effects.
   *@author Danno Ferrin
   */
  public class CommandLineCompiler extends Compiler implements Mangler {
  
      String javaFileName;
      String classFileName;
      String pkgName;
      String className;
      File jsp;
      String outputDir;
  
      public CommandLineCompiler(JspCompilationContext ctxt) {
          super(ctxt);
  
          jsp = new File(ctxt.getJspFile());
          outputDir =  ctxt.getOptions().getScratchDir().getAbsolutePath();
          setMangler(this);
  
          computePackageName();
          className = getBaseClassName();
          computeClassFileName();
          computeJavaFileName();
      };
  
  
      /**
       * Always outDated.  (Of course we are, this is an explicit invocation
       *@returns true
       */
      protected boolean isOutDated() {
          return true;
      };
  
  
      public final void computeJavaFileName() {
  	javaFileName = className + ".java";
  	if (outputDir != null && !outputDir.equals(""))
  	    javaFileName = outputDir + File.separatorChar + javaFileName;
      }
  
      void computeClassFileName() {
          String prefix = getPrefix(jsp.getPath());
          classFileName = prefix + getBaseClassName() + ".class";
  	if (outputDir != null && !outputDir.equals(""))
  	    classFileName = outputDir + File.separatorChar + classFileName;
      }
  
      public static String [] keywords = {
          "abstract", "boolean", "break", "byte",
          "case", "catch", "char", "class",
          "const", "continue", "default", "do",
          "double", "else", "extends", "final",
          "finally", "float", "for", "goto",
          "if", "implements", "import",
          "instanceof", "int", "interface",
          "long", "native", "new", "package",
          "private", "protected", "public",
          "return", "short", "static", "super",
          "switch", "synchronized", "this",
          "throw", "throws", "transient",
          "try", "void", "volatile", "while"
      };
  
      void computePackageName() {
  	String pathName = jsp.getPath();
  	StringBuffer modifiedpkgName = new StringBuffer ();
          int indexOfSepChar = pathName.lastIndexOf(File.separatorChar);
  
  	if (indexOfSepChar == -1 || indexOfSepChar == 0)
  	    pkgName = null;
  	else {
  	    for (int i = 0; i < keywords.length; i++) {
  		char fs = File.separatorChar;
  		int index1 = pathName.indexOf(fs + keywords[i]);
  		int index2 = pathName.indexOf(keywords[i]);
  		if (index1 == -1 && index2 == -1) continue;
  		int index = (index2 == -1) ? index1 : index2;
  		while (index != -1) {
  		    String tmpathName = pathName.substring (0,index+1) + '%';
  		    pathName = tmpathName + pathName.substring (index+2);
  		    index = pathName.indexOf(fs + keywords[i]);
  		}
  	    }
  	
  	    // XXX fix for paths containing '.'.
  	    // Need to be more elegant here.
              pathName = pathName.replace('.','_');
  	
  	    pkgName = pathName.substring(0, pathName.lastIndexOf(
  	    		File.separatorChar)).replace(File.separatorChar, '.');
  	    for (int i=0; i<pkgName.length(); i++)
  		if (Character.isLetter(pkgName.charAt(i)) == true ||
  		    pkgName.charAt(i) == '.') {
  		    modifiedpkgName.append(pkgName.substring(i,i+1));
  		}
  		else
  		    modifiedpkgName.append(mangleChar(pkgName.charAt(i)));
  
  	    if (modifiedpkgName.charAt(0) == '.') {
                  String modifiedpkgNameString = modifiedpkgName.toString();
                  pkgName = modifiedpkgNameString.substring(1,
                                                           modifiedpkgName.length ());
              }
  	    else
  	        pkgName = modifiedpkgName.toString();
  	}
  
      }
  
  					
      private final String getInitialClassName() {
          String prefix = getPrefix(jsp.getPath());
  
          return prefix + getBaseClassName() + Constants.JSP_TOKEN + "0";
      }
  
      private final String getBaseClassName() {
  	String className;
  
          if (jsp.getName().endsWith(".jsp"))
              className = jsp.getName().substring(0, jsp.getName().length() - 4);
          else
              className = jsp.getName();
  
  	
  	// Fix for invalid characters. If you think of more add to the list.
  	StringBuffer modifiedClassName = new StringBuffer();
  	for (int i = 0; i < className.length(); i++) {
  	    if (Character.isLetterOrDigit(className.charAt(i)) == true)
  		modifiedClassName.append(className.substring(i,i+1));
  	    else
  		modifiedClassName.append(mangleChar(className.charAt(i)));
  	}
  	
  	return modifiedClassName.toString();
      }
  
      private final String getPrefix(String pathName) {
  	if (pathName != null) {
  	    StringBuffer modifiedName = new StringBuffer();
  	    for (int i = 0; i < pathName.length(); i++) {
  		if (Character.isLetter(pathName.charAt(i)) == true)
  		    modifiedName.append(pathName.substring(i,i+1));
  		else
  		    modifiedName.append(mangleChar(pathName.charAt(i)));
   	    }
  	    return modifiedName.toString();
  	}
  	else
              return "";
      }
  
      private static final String mangleChar(char ch) {
  	String s = Integer.toHexString(ch);
  	int nzeros = 5 - s.length();
  	char[] result = new char[6];
  	result[0] = '_';
  	for (int i = 1; i <= nzeros; i++)
  	    result[i] = '0';
  	for (int i = nzeros+1, j = 0; i < 6; i++, j++)
  	    result[i] = s.charAt(j);
  	return new String(result);
      }
  
  
      public final String getPackageName() {
          return pkgName;
      }
  
      public final String getClassName() {
          return className;
      }
  
      public final String getJavaFileName() {
          return javaFileName;
      }
  
      public final String getClassFileName() {
          return classFileName;
      }
  
  
  }
  
  
  
  1.27      +2 -0      jakarta-tomcat/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/build.xml,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- build.xml	2000/02/03 07:13:41	1.26
  +++ build.xml	2000/02/07 07:51:20	1.27
  @@ -39,6 +39,7 @@
       <copyfile src="LICENSE" dest="${tomcat.build}/LICENSE"/>
   
       <chmod perm="+x" src="${tomcat.build}/bin/tomcat.sh"/>
  +    <chmod perm="+x" src="${tomcat.build}/bin/jspc.sh"/>
       <chmod perm="+x" src="${tomcat.build}/bin/ant"/>
       <chmod perm="+x" src="${tomcat.build}/bin/startup.sh"/>
       <chmod perm="+x" src="${tomcat.build}/bin/shutdown.sh"/>
  @@ -118,6 +119,7 @@
   
       <!-- Change permissions for unix -->
       <chmod perm="+x" src="${tomcat.home}/bin/tomcat.sh"/>
  +    <chmod perm="+x" src="${tomcat.home}/bin/jspc.sh"/>
       <chmod perm="+x" src="${tomcat.home}/bin/ant"/>
       <chmod perm="+x" src="${tomcat.home}/bin/startup.sh"/>
       <chmod perm="+x" src="${tomcat.home}/bin/shutdown.sh"/>
  
  
  
  1.10      +14 -0     jakarta-tomcat/src/share/org/apache/jasper/resources/messages.properties
  
  Index: messages.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/resources/messages.properties,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- messages.properties	2000/01/21 04:17:22	1.9
  +++ messages.properties	2000/02/07 07:51:21	1.10
  @@ -141,3 +141,17 @@
   jsp.warning.compiler.class.cantcreate=Can't create an instance of specified compiler plugin class {0} due to {1}. Will default to Sun Java Compiler.
   jsp.warning.compiler.class.notfound=Specified compiler plugin class {0} not found. Will default to Sun Java Compiler.
   jsp.warning.compiler.path.notfound=Specified compiler path {0} not found. Will default to system PATH.
  +jsp.error.jspc.uriroot_not_dir=The -uriroot option must specify a pre-existing directory
  +jspc.usage=Usage: jspc <options> [--] <jsp files>\n\
  +where options include:\n\
  +\    -q          Quite mode (same as -v0)\n\
  +\    -v[#]       Verbose mode (optional number is level, default is 2)\n\
  +\    -d <dir>    Output Directory\n\
  +\    -ieplugin   Java Plugin classid for IE\n\
  +\    -p <name>   Name of target package\n\
  +\    -c <name>   Name of target class name\n\
  +\                (only applies to first JSP page)\n\
  +\    -uribase    The uri directory compilations shoule be relative to\n\
  +\                (Default is "/")\n\
  +\    -uriroot    The root directory that uri files should be resolced against\n\
  +\                (Default is the directory jspc is invoked from)\n\
  
  
  
  1.5       +20 -71    jakarta-tomcat/src/share/org/apache/jasper/runtime/JspLoader.java
  
  Index: JspLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/runtime/JspLoader.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- JspLoader.java	2000/01/24 05:54:52	1.4
  +++ JspLoader.java	2000/02/07 07:51:21	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/runtime/JspLoader.java,v 1.4 2000/01/24 05:54:52 shemnon Exp $
  - * $Revision: 1.4 $
  - * $Date: 2000/01/24 05:54:52 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/runtime/JspLoader.java,v 1.5 2000/02/07 07:51:21 shemnon Exp $
  + * $Revision: 1.5 $
  + * $Date: 2000/02/07 07:51:21 $
    *
    * ====================================================================
    * 
  @@ -73,10 +73,6 @@
   import java.util.zip.ZipFile;
   import java.util.zip.ZipEntry;
   
  -import javax.servlet.ServletContext;
  -import javax.servlet.http.HttpServletRequest;
  -import javax.servlet.http.HttpServletResponse;
  -
   import org.apache.jasper.JasperException;
   import org.apache.jasper.Constants;
   import org.apache.jasper.JspCompilationContext;
  @@ -102,26 +98,21 @@
    * @author Harish Prabandham
    */
   public class JspLoader extends ClassLoader {
  -    Hashtable loadedJSPs = new Hashtable();
       ClassLoader parent;
  -    ServletContext context;
       Options options;
       
   
  -    JspLoader(ServletContext context, 
  -              ClassLoader cl, Options options)
  +    /*
  +     * This should be factoried out
  +     */
  +    public JspLoader(ClassLoader cl, Options options)
       {
   	//	super(cl); // JDK 1.2 FIXME
   	super();
  -        this.context = context;
   	this.parent = cl;
           this.options = options;
       }
   
  -    public Class getJspServletClass(String name) {
  -	return (Class) loadedJSPs.get(name);
  -    }
  -
       protected synchronized Class loadClass(String name, boolean resolve)
   	throws ClassNotFoundException
       {
  @@ -158,8 +149,9 @@
   		className.lastIndexOf(".")+1;
   	    int end = className.lastIndexOf("_jsp_");
   
  -	    if (end <= 0) {     // this is a class that the JSP file depends on (example: class
  -                                // in a tag library)
  +	    if (end <= 0) {     
  +                // this is a class that the JSP file depends on 
  +                // (example: class in a tag library)
                   byte[] classBytes = loadClassDataFromJar(className);
                   if (classBytes == null)
                       throw new ClassNotFoundException(className);
  @@ -187,7 +179,7 @@
                   return defClass(className, classBytes);
               }
   	} catch (Exception ex) {
  -	    throw new ClassNotFoundException(Constants.getString(
  +            throw new ClassNotFoundException(Constants.getString(
   	    				     "jsp.error.unable.loadclass", 
   					      new Object[] {className}));
   	}
  @@ -201,65 +193,21 @@
           return defineClass(className, classData, 0, classData.length);
       }
   
  -    /*  Check if we need to reload a JSP page.
  -     *
  -     *  Side-effect: re-compile the JSP page.
  -     *
  -     *  @param classpath explicitly set the JSP compilation path.
  -     *  @return true if JSP files is newer
  -     */
  -    public synchronized boolean loadJSP(String name, String classpath, 
  -	boolean isErrorPage, HttpServletRequest req, HttpServletResponse res) 
  -	throws JasperException, FileNotFoundException 
  -    {
  -	Class jspClass = (Class) loadedJSPs.get(name);
  -	boolean firstTime = jspClass == null;
  -
  -        JspCompilationContext ctxt = new JspEngineContext(this, classpath,
  -                                                     context, name, 
  -                                                     isErrorPage, options,
  -                                                     req, res);
  -	boolean outDated = false; 
  -
  -        Compiler compiler = ctxt.createCompiler();
  -        
  -        try {
  -            outDated = compiler.compile();
  -        } catch (FileNotFoundException ex) {
  -            throw ex;
  -        } catch (JasperException ex) {
  -            throw ex;
  -        } catch (Exception ex) {
  -            throw new JasperException(Constants.getString("jsp.error.unable.compile"),
  -                                      ex);
  -        }
  -
  -	// Reload only if it's outdated
  -	if((jspClass == null) || outDated) {
  -	    try {
  -		jspClass = loadClass(ctxt.getFullClassName(), true);
  -	    } catch (ClassNotFoundException cex) {
  -		throw new JasperException(Constants.getString("jsp.error.unable.load"), 
  -					  cex);
  -	    }
  -	    loadedJSPs.put(name, jspClass);
  -	}
  -	
  -	return outDated;
  -    }
  -
       private Vector jars = new Vector();
       
       private byte[] loadClassDataFromJar(String className) {
           String entryName = className.replace('.','/')+".class";
   	InputStream classStream = null;
  -        
  +	//System.out.println("Loading " + className);
  +
           for(int i = 0; i < jars.size(); i++) {
               File thisFile = new File((String) jars.elementAt(i));
               try {
  +                //System.out.println(" - trying " + thisFile.getAbsolutePath());
                   // check if it exists...
  -                if (!thisFile.exists())
  -                    return null;
  +                if (!thisFile.exists()) {
  +                    continue; 
  +                };
                   
                   if (thisFile.isFile()) {
                       ZipFile zip = new ZipFile(thisFile);
  @@ -273,8 +221,9 @@
   			zip.close();
   		    }
                   } else { // its a directory...
  -                    File classFile = new File(thisFile,
  -                                              entryName.replace('/', File.separatorChar));
  +                    File classFile = 
  +                        new File(thisFile,
  +                                 entryName.replace('/', File.separatorChar));
                       if (classFile.exists()) {
                           classStream = new FileInputStream(classFile);
                           byte[] classData = getClassData(classStream);
  
  
  
  1.15      +60 -4     jakarta-tomcat/src/share/org/apache/jasper/runtime/JspServlet.java
  
  Index: JspServlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/runtime/JspServlet.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- JspServlet.java	2000/01/24 05:54:52	1.14
  +++ JspServlet.java	2000/02/07 07:51:22	1.15
  @@ -77,7 +77,10 @@
   import org.apache.jasper.Constants;
   import org.apache.jasper.Options;
   import org.apache.jasper.EmbededServletOptions;
  +import org.apache.jasper.JspCompilationContext;
  +import org.apache.jasper.JspEngineContext;
   
  +import org.apache.jasper.compiler.Compiler;
   
   /**
    * The JSP engine (a.k.a Jasper)! 
  @@ -86,6 +89,7 @@
    * @author Harish Prabandham
    */
   public class JspServlet extends HttpServlet {
  +
       class JspServletWrapper {
   	HttpJspPage theServlet;
   	String jspUri;
  @@ -99,7 +103,8 @@
   	
   	private void load() throws JasperException, ServletException {
   	    try {  
  -		Class servletClass = loader.getJspServletClass(jspUri);
  +		Class servletClass = (Class) loadedJSPs.get(jspUri);
  +			//loader.getJspServletClass(jspUri);
   		// This is for the original protocol.
   		destroy();
   		theServlet = (HttpJspPage) servletClass.newInstance();
  @@ -135,7 +140,9 @@
                                 new Object[] { accordingto, cp }, 
                                 Constants.MED_VERBOSITY);
   
  -	    if (loader.loadJSP(jspUri, cp, isErrorPage, req, res) || theServlet == null) {
  +	    //if (loader.loadJSP(jspUri, cp, isErrorPage, req, res) || theServlet == null) {
  +            if (loadJSP(jspUri, cp, isErrorPage, req, res) 
  +                    || theServlet == null) {
                   load();
               }
   	}
  @@ -182,6 +189,7 @@
   	
       ServletContext context = null;
       Hashtable jsps = new Hashtable();
  +    Hashtable loadedJSPs = new Hashtable();
       ServletConfig config;
       JspLoader loader;
       Options options;
  @@ -222,8 +230,7 @@
                                     "<none>"
                                 }, Constants.MED_VERBOSITY);
               }
  -            this.loader = new JspLoader(context, 
  -                                        parentClassLoader, 
  +            this.loader = new JspLoader(parentClassLoader, 
                                           options);
   
               if (firstTime) {
  @@ -377,6 +384,55 @@
   	Enumeration servlets = jsps.elements();
   	while (servlets.hasMoreElements()) 
   	    ((JspServletWrapper) servlets.nextElement()).destroy();
  +    }
  +
  +
  +    /*  Check if we need to reload a JSP page.
  +     *
  +     *  Side-effect: re-compile the JSP page.
  +     *
  +     *  @param classpath explicitly set the JSP compilation path.
  +     *  @return true if JSP files is newer
  +     */
  +    public synchronized boolean loadJSP(String name, String classpath, 
  +	boolean isErrorPage, HttpServletRequest req, HttpServletResponse res) 
  +	throws JasperException, FileNotFoundException 
  +    {
  +	Class jspClass = (Class) loadedJSPs.get(name);
  +	boolean firstTime = jspClass == null;
  +
  +        JspCompilationContext ctxt = new JspEngineContext(loader, classpath,
  +                                                     context, name, 
  +                                                     isErrorPage, options,
  +                                                     req, res);
  +	boolean outDated = false; 
  +
  +        Compiler compiler = ctxt.createCompiler();
  +        
  +        try {
  +            outDated = compiler.compile();
  +        } catch (FileNotFoundException ex) {
  +            throw ex;
  +        } catch (JasperException ex) {
  +            throw ex;
  +        } catch (Exception ex) {
  +            throw new JasperException(Constants.getString("jsp.error.unable.compile"),
  +                                      ex);
  +        }
  +
  +	// Reload only if it's outdated
  +	if((jspClass == null) || outDated) {
  +	    try {
  +		jspClass = loader.loadClass(ctxt.getFullClassName());
  +                        //loadClass(ctxt.getFullClassName(), true);
  +	    } catch (ClassNotFoundException cex) {
  +		throw new JasperException(Constants.getString("jsp.error.unable.load"), 
  +					  cex);
  +	    }
  +	    loadedJSPs.put(name, jspClass);
  +	}
  +	
  +	return outDated;
       }
   
   }