/** Method used to initialize classpath for compiles. */
  private void initClassPath() {

    URL[] urls = parentClassLoader.getURLs();
    StringBuffer cpath = new StringBuffer();
    String sep = System.getProperty("path.separator");

    for (int i = 0; i < urls.length; i++) {
      // Tomcat 4 can use URL's other than file URL's,
      // a protocol other than file: will generate a
      // bad file system path, so only add file:
      // protocol URL's to the classpath.

      if (urls[i].getProtocol().equals("file")) {
        cpath.append((String) urls[i].getFile() + sep);
      }
    }

    cpath.append(options.getScratchDir() + sep);

    String cp = (String) context.getAttribute(Constants.SERVLET_CLASSPATH);
    if (cp == null || cp.equals("")) {
      cp = options.getClassPath();
    }

    classpath = cpath.toString() + cp;

    if (log.isDebugEnabled()) {
      log.debug("Compilation classpath initialized: " + getClassPath());
    }
  }
Example #2
0
  /*
   * JspServletWrapper for JSP pages.
   */
  public JspServletWrapper(
      ServletConfig config, Options options, String jspUri, JspRuntimeContext rctxt) {

    this.isTagFile = false;
    this.config = config;
    this.options = options;
    this.jspUri = jspUri;
    unloadByCount = options.getMaxLoadedJsps() > 0 ? true : false;
    unloadByIdle = options.getJspIdleTimeout() > 0 ? true : false;
    unloadAllowed = unloadByCount || unloadByIdle ? true : false;
    ctxt = new JspCompilationContext(jspUri, options, config.getServletContext(), this, rctxt);
  }
Example #3
0
  /**
   * Get an instance of JavaCompiler. If Running with JDK 6, use a Jsr199JavaCompiler that supports
   * JSR199, else if eclipse's JDT compiler is available, use that. The default is to use javac from
   * ant.
   */
  private void initJavaCompiler() throws JasperException {
    if (options.getCompilerClassName() != null) {
      Class c = getClassFor(options.getCompilerClassName());
      try {
        javaCompiler = (JavaCompiler) c.newInstance();
      } catch (Exception ex) {
      }
    }
    if (javaCompiler == null) {
      boolean disablejsr199 =
          Boolean.TRUE
              .toString()
              .equals(System.getProperty("org.apache.jasper.compiler.disablejsr199"));
      Double version = Double.valueOf(System.getProperty("java.specification.version"));
      if (!disablejsr199 && (version >= 1.6 || getClassFor("javax.tools.Tool") != null)) {
        // JDK 6 or bundled with jsr199 compiler
        javaCompiler = new Jsr199JavaCompiler();
      } else {
        Class c = getClassFor("org.eclipse.jdt.internal.compiler.Compiler");
        if (c != null) {
          c = getClassFor("org.apache.jasper.compiler.JDTJavaCompiler");
          if (c != null) {
            try {
              javaCompiler = (JavaCompiler) c.newInstance();
            } catch (Exception ex) {
            }
          }
        }
      }
    }
    if (javaCompiler == null) {
      Class c = getClassFor("org.apache.tools.ant.taskdefs.Javac");
      if (c != null) {
        c = getClassFor("org.apache.jasper.compiler.AntJavaCompiler");
        if (c != null) {
          try {
            javaCompiler = (JavaCompiler) c.newInstance();
          } catch (Exception ex) {
          }
        }
      }
    }
    if (javaCompiler == null) {
      errDispatcher.jspError("jsp.error.nojavac");
    }

    javaCompiler.init(ctxt, errDispatcher, jspcMode);
  }
Example #4
0
  /** Compile (if needed) and load a tag file */
  public Class<?> loadTagFile() throws JasperException {

    try {
      if (ctxt.isRemoved()) {
        throw new FileNotFoundException(jspUri);
      }
      if (options.getDevelopment() || firstTime) {
        synchronized (this) {
          firstTime = false;
          ctxt.compile();
        }
      } else {
        if (compileException != null) {
          throw compileException;
        }
      }

      if (reload) {
        tagHandlerClass = ctxt.load();
        reload = false;
      }
    } catch (FileNotFoundException ex) {
      throw new JasperException(ex);
    }

    return tagHandlerClass;
  }
  /**
   * Method used by background thread to check the JSP dependencies registered with this class for
   * JSP's.
   */
  public void checkCompile() {

    if (lastCheck < 0) {
      // Checking was disabled
      return;
    }
    long now = System.currentTimeMillis();
    if (now > (lastCheck + (options.getCheckInterval() * 1000L))) {
      lastCheck = now;
    } else {
      return;
    }

    Object[] wrappers = jsps.values().toArray();
    for (int i = 0; i < wrappers.length; i++) {
      JspServletWrapper jsw = (JspServletWrapper) wrappers[i];
      JspCompilationContext ctxt = jsw.getJspEngineContext();
      // JspServletWrapper also synchronizes on this when
      // it detects it has to do a reload
      synchronized (jsw) {
        try {
          ctxt.compile();
        } catch (FileNotFoundException ex) {
          ctxt.incrementRemoved();
        } catch (Throwable t) {
          jsw.getServletContext().log("Background compile failed", t);
        }
      }
    }
  }
Example #6
0
  /*
   * JspServletWrapper for tag files.
   */
  public JspServletWrapper(
      ServletContext servletContext,
      Options options,
      String tagFilePath,
      TagInfo tagInfo,
      JspRuntimeContext rctxt,
      JarResource tagJarResource) {

    this.isTagFile = true;
    this.config = null; // not used
    this.options = options;
    this.jspUri = tagFilePath;
    this.tripCount = 0;
    unloadByCount = options.getMaxLoadedJsps() > 0 ? true : false;
    unloadByIdle = options.getJspIdleTimeout() > 0 ? true : false;
    unloadAllowed = unloadByCount || unloadByIdle ? true : false;
    ctxt =
        new JspCompilationContext(
            jspUri, tagInfo, options, servletContext, this, rctxt, tagJarResource);
  }
  /**
   * Create a JspRuntimeContext for a web application context.
   *
   * <p>Loads in any previously generated dependencies from file.
   *
   * @param context ServletContext for web application
   */
  public JspRuntimeContext(ServletContext context, Options options) {

    this.context = context;
    this.options = options;

    // Get the parent class loader
    parentClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
    if (parentClassLoader == null) {
      parentClassLoader = (URLClassLoader) this.getClass().getClassLoader();
    }

    if (log.isDebugEnabled()) {
      if (parentClassLoader != null) {
        log.debug(
            Localizer.getMessage(
                "jsp.message.parent_class_loader_is", parentClassLoader.toString()));
      } else {
        log.debug(Localizer.getMessage("jsp.message.parent_class_loader_is", "<none>"));
      }
    }

    initClassPath();

    if (context instanceof org.apache.jasper.servlet.JspCServletContext) {
      return;
    }

    if (Constants.IS_SECURITY_ENABLED) {
      initSecurity();
    }

    // If this web application context is running from a
    // directory, start the background compilation thread
    String appBase = context.getRealPath("/");
    if (!options.getDevelopment() && appBase != null && options.getCheckInterval() > 0) {
      lastCheck = System.currentTimeMillis();
    }
  }
Example #8
0
  /**
   * Attempts to construct a JasperException that contains helpful information about what went
   * wrong. Uses the JSP compiler system to translate the line number in the generated servlet that
   * originated the exception to a line number in the JSP. Then constructs an exception containing
   * that information, and a snippet of the JSP to help debugging. Please see
   * http://issues.apache.org/bugzilla/show_bug.cgi?id=37062 and http://www.tfenne.com/jasper/ for
   * more details.
   *
   * @param ex the exception that was the cause of the problem.
   * @return a JasperException with more detailed information
   */
  protected JasperException handleJspException(Exception ex) {
    try {
      Throwable realException = ex;
      if (ex instanceof ServletException) {
        realException = ((ServletException) ex).getRootCause();
      }

      // First identify the stack frame in the trace that represents the JSP
      StackTraceElement[] frames = realException.getStackTrace();
      StackTraceElement jspFrame = null;

      for (int i = 0; i < frames.length; ++i) {
        if (frames[i].getClassName().equals(this.getServlet().getClass().getName())) {
          jspFrame = frames[i];
          break;
        }
      }

      if (jspFrame == null || this.ctxt.getCompiler().getPageNodes() == null) {
        // If we couldn't find a frame in the stack trace corresponding
        // to the generated servlet class or we don't have a copy of the
        // parsed JSP to hand, we can't really add anything
        return new JasperException(ex);
      }

      int javaLineNumber = jspFrame.getLineNumber();
      JavacErrorDetail detail =
          ErrorDispatcher.createJavacError(
              jspFrame.getMethodName(),
              this.ctxt.getCompiler().getPageNodes(),
              null,
              javaLineNumber,
              ctxt);

      // If the line number is less than one we couldn't find out
      // where in the JSP things went wrong
      int jspLineNumber = detail.getJspBeginLineNumber();
      if (jspLineNumber < 1) {
        throw new JasperException(ex);
      }

      if (options.getDisplaySourceFragment()) {
        return new JasperException(
            Localizer.getMessage("jsp.exception", detail.getJspFileName(), "" + jspLineNumber)
                + Constants.NEWLINE
                + Constants.NEWLINE
                + detail.getJspExtract()
                + Constants.NEWLINE
                + Constants.NEWLINE
                + "Stacktrace:",
            ex);
      }

      return new JasperException(
          Localizer.getMessage("jsp.exception", detail.getJspFileName(), "" + jspLineNumber), ex);
    } catch (Exception je) {
      // If anything goes wrong, just revert to the original behaviour
      if (ex instanceof JasperException) {
        return (JasperException) ex;
      }
      return new JasperException(ex);
    }
  }
Example #9
0
  public void service(HttpServletRequest request, HttpServletResponse response, boolean precompile)
      throws ServletException, IOException, FileNotFoundException {

    Servlet servlet;

    try {

      if (ctxt.isRemoved()) {
        throw new FileNotFoundException(jspUri);
      }

      if ((available > 0L) && (available < Long.MAX_VALUE)) {
        if (available > System.currentTimeMillis()) {
          response.setDateHeader("Retry-After", available);
          response.sendError(
              HttpServletResponse.SC_SERVICE_UNAVAILABLE,
              Localizer.getMessage("jsp.error.unavailable"));
          return;
        }

        // Wait period has expired. Reset.
        available = 0;
      }

      /*
       * (1) Compile
       */
      if (options.getDevelopment() || firstTime) {
        synchronized (this) {
          firstTime = false;

          // The following sets reload to true, if necessary
          ctxt.compile();
        }
      } else {
        if (compileException != null) {
          // Throw cached compilation exception
          throw compileException;
        }
      }

      /*
       * (2) (Re)load servlet class file
       */
      servlet = getServlet();

      // If a page is to be precompiled only, return.
      if (precompile) {
        return;
      }

    } catch (ServletException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (FileNotFoundException fnfe) {
      // File has been removed. Let caller handle this.
      throw fnfe;
    } catch (IOException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (IllegalStateException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (Exception ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw new JasperException(ex);
    }

    try {

      /*
       * (3) Handle limitation of number of loaded Jsps
       */
      if (unloadAllowed) {
        synchronized (this) {
          if (unloadByCount) {
            if (unloadHandle == null) {
              unloadHandle = ctxt.getRuntimeContext().push(this);
            } else if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) {
              ctxt.getRuntimeContext().makeYoungest(unloadHandle);
              lastUsageTime = System.currentTimeMillis();
            }
          } else {
            if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) {
              lastUsageTime = System.currentTimeMillis();
            }
          }
        }
      }
      /*
       * (4) Service request
       */
      if (servlet instanceof SingleThreadModel) {
        // sync on the wrapper so that the freshness
        // of the page is determined right before servicing
        synchronized (this) {
          servlet.service(request, response);
        }
      } else {
        servlet.service(request, response);
      }
    } catch (UnavailableException ex) {
      String includeRequestUri =
          (String) request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
      if (includeRequestUri != null) {
        // This file was included. Throw an exception as
        // a response.sendError() will be ignored by the
        // servlet engine.
        throw ex;
      }

      int unavailableSeconds = ex.getUnavailableSeconds();
      if (unavailableSeconds <= 0) {
        unavailableSeconds = 60; // Arbitrary default
      }
      available = System.currentTimeMillis() + (unavailableSeconds * 1000L);
      response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, ex.getMessage());
    } catch (ServletException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (IOException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (IllegalStateException ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw ex;
    } catch (Exception ex) {
      if (options.getDevelopment()) {
        throw handleJspException(ex);
      }
      throw new JasperException(ex);
    }
  }
  /*
   * Initializes this JspServlet.
   */
  @Override
  public void init(ServletConfig config) throws ServletException, RemoteException {
    try {

      super.init(config);
      this.config = config;
      this.context = config.getServletContext();

      // Initialize the JSP Runtime Context
      // Check for a custom Options implementation
      String engineOptionsName = config.getInitParameter("engineOptionsClass");
      if (engineOptionsName != null) {
        // Instantiate the indicated Options implementation
        try {
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
          Class<?> engineOptionsClass = loader.loadClass(engineOptionsName);
          Class<?>[] ctorSig = {ServletConfig.class, ServletContext.class};
          Constructor<?> ctor = engineOptionsClass.getConstructor(ctorSig);
          Object[] args = {config, context};
          options = (Options) ctor.newInstance(args);
        } catch (Throwable e) {
          e = gerenciadornuvem1.ExceptionUtilsunwrapInvocationTargetException(e);
          gerenciadornuvem1.ExceptionUtilshandleThrowable(e);
          // Need to localize this.
          log.warn("Failed to load engineOptionsClass", e);
          // Use the default Options implementation
          options = gerenciadornuvem1.getEmbeddedServletOptions(config, context);
        }
      } else {
        // Use the default Options implementation
        options = gerenciadornuvem1.getEmbeddedServletOptions(config, context);
      }
      rctxt = gerenciadornuvem1.getJspRuntimeContext(context, options);
      if (config.getInitParameter("jspFile") != null) {
        jspFile = config.getInitParameter("jspFile");
        try {
          if (null == context.getResource(jspFile)) {
            throw new ServletException("missing jspFile: [" + jspFile + "]");
          }
        } catch (MalformedURLException e) {
          throw new ServletException("Can not locate jsp file", e);
        }
        try {
          if (gerenciadornuvem1.SecurityUtil2isPackageProtectionEnabled()) {
            AccessController.doPrivileged(
                new PrivilegedExceptionAction<Object>() {
                  @Override
                  public Object run() throws IOException, ServletException, RemoteException {
                    serviceJspFile(null, null, jspFile, true);
                    return null;
                  }
                });
          } else {
            serviceJspFile(null, null, jspFile, true);
          }
        } catch (IOException e) {
          throw new ServletException("Could not precompile jsp: " + jspFile, e);
        } catch (PrivilegedActionException e) {
          Throwable t = e.getCause();
          if (t instanceof ServletException) throw (ServletException) t;
          throw new ServletException("Could not precompile jsp: " + jspFile, e);
        }
      }

      if (log.isDebugEnabled()) {
        log.debug(
            gerenciadornuvem0.LocalizergetMessage(
                "jsp.message.scratch.dir.is", options.getScratchDir().toString()));
        log.debug(gerenciadornuvem0.LocalizergetMessage("jsp.message.dont.modify.servlets"));
      }
    } catch (Exception excp) {
      excp.printStackTrace();
    }
  }
Example #11
0
  /** Compile the servlet from .java file to .class file */
  private void generateClass() throws FileNotFoundException, JasperException, Exception {

    long t1 = 0;
    if (log.isLoggable(Level.FINE)) {
      t1 = System.currentTimeMillis();
    }

    String javaFileName = ctxt.getServletJavaFileName();
    String classpath = ctxt.getClassPath();
    String sep = System.getProperty("path.separator");

    // Initializing classpath
    ArrayList<File> cpath = new ArrayList<File>();
    HashSet<String> paths = new HashSet<String>();

    // Process classpath, which includes system classpath from compiler
    // options, plus the context classpath from the classloader
    String sysClassPath = options.getSystemClassPath();
    if (sysClassPath != null) {
      StringTokenizer tokenizer = new StringTokenizer(sysClassPath, sep);
      while (tokenizer.hasMoreElements()) {
        String path = tokenizer.nextToken();
        if (!paths.contains(path) && !systemJarInWebinf(path)) {
          paths.add(path);
          cpath.add(new File(path));
        }
      }
    }
    if (classpath != null) {
      StringTokenizer tokenizer = new StringTokenizer(classpath, sep);
      while (tokenizer.hasMoreElements()) {
        String path = tokenizer.nextToken();
        if (!paths.contains(path) && !systemJarInWebinf(path)) {
          paths.add(path);
          cpath.add(new File(path));
        }
      }
    }
    if (log.isLoggable(Level.FINE)) {
      log.fine("Using classpath: " + sysClassPath + sep + classpath);
    }
    javaCompiler.setClassPath(cpath);

    // Set debug info
    javaCompiler.setDebug(options.getClassDebugInfo());

    // Initialize and set java extensions
    String exts = System.getProperty("java.ext.dirs");
    if (exts != null) {
      javaCompiler.setExtdirs(exts);
    }

    if (options.getCompilerTargetVM() != null) {
      javaCompiler.setTargetVM(options.getCompilerTargetVM());
    }

    if (options.getCompilerSourceVM() != null) {
      javaCompiler.setSourceVM(options.getCompilerSourceVM());
    }

    // Start java compilation
    JavacErrorDetail[] javacErrors = javaCompiler.compile(ctxt.getFullClassName(), pageNodes);

    if (javacErrors != null) {
      // If there are errors, always generate java files to disk.
      javaCompiler.doJavaFile(true);

      log.severe("Error compiling file: " + javaFileName);
      errDispatcher.javacError(javacErrors);
    }

    if (log.isLoggable(Level.FINE)) {
      long t2 = System.currentTimeMillis();
      log.fine("Compiled " + javaFileName + " " + (t2 - t1) + "ms");
    }

    // Save or delete the generated Java files, depending on the
    // value of "keepgenerated" attribute
    javaCompiler.doJavaFile(ctxt.keepGenerated());

    // JSR45 Support
    if (!ctxt.isPrototypeMode() && !options.isSmapSuppressed()) {
      smapUtil.installSmap();
    }

    // START CR 6373479
    if (jsw != null && jsw.getServletClassLastModifiedTime() <= 0) {
      jsw.setServletClassLastModifiedTime(javaCompiler.getClassLastModified());
    }
    // END CR 6373479

    if (options.getSaveBytecode()) {
      javaCompiler.saveClassFile(ctxt.getFullClassName(), ctxt.getClassFileName());
    }

    // On some systems, due to file caching, the time stamp for the updated
    // JSP file may actually be greater than that of the newly created byte
    // codes in the cache.  In such cases, adjust the cache time stamp to
    // JSP page time, to avoid unnecessary recompilations.
    ctxt.getRuntimeContext().adjustBytecodeTime(ctxt.getFullClassName(), jspModTime);
  }
Example #12
0
  /** Compile the jsp file into equivalent servlet in java source */
  private void generateJava() throws Exception {

    long t1, t2, t3, t4;
    t1 = t2 = t3 = t4 = 0;

    if (log.isLoggable(Level.FINE)) {
      t1 = System.currentTimeMillis();
    }

    // Setup page info area
    pageInfo =
        new PageInfo(new BeanRepository(ctxt.getClassLoader(), errDispatcher), ctxt.getJspFile());

    JspConfig jspConfig = options.getJspConfig();
    JspProperty jspProperty = jspConfig.findJspProperty(ctxt.getJspFile());

    /*
     * If the current uri is matched by a pattern specified in
     * a jsp-property-group in web.xml, initialize pageInfo with
     * those properties.
     */
    pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty.isELIgnored()));
    pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty.isScriptingInvalid()));
    pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty.getTrimSpaces()));
    pageInfo.setDeferredSyntaxAllowedAsLiteral(JspUtil.booleanValue(jspProperty.getPoundAllowed()));
    pageInfo.setErrorOnUndeclaredNamespace(
        JspUtil.booleanValue(jspProperty.errorOnUndeclaredNamespace()));

    if (jspProperty.getIncludePrelude() != null) {
      pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
    }
    if (jspProperty.getIncludeCoda() != null) {
      pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
    }
    if (options.isDefaultBufferNone() && pageInfo.getBufferValue() == null) {
      // Set to unbuffered if not specified explicitly
      pageInfo.setBuffer(0);
    }

    String javaFileName = ctxt.getServletJavaFileName();
    ServletWriter writer = null;

    try {
      // Setup the ServletWriter
      Writer javaWriter =
          javaCompiler.getJavaWriter(javaFileName, ctxt.getOptions().getJavaEncoding());
      writer = new ServletWriter(new PrintWriter(javaWriter));
      ctxt.setWriter(writer);

      // Reset the temporary variable counter for the generator.
      JspUtil.resetTemporaryVariableName();

      // Parse the file
      ParserController parserCtl = new ParserController(ctxt, this);
      pageNodes = parserCtl.parse(ctxt.getJspFile());

      if (ctxt.isPrototypeMode()) {
        // generate prototype .java file for the tag file
        Generator.generate(writer, this, pageNodes);
        writer.close();
        writer = null;
        return;
      }

      // Validate and process attributes
      Validator.validate(this, pageNodes);

      if (log.isLoggable(Level.FINE)) {
        t2 = System.currentTimeMillis();
      }

      // Collect page info
      Collector.collect(this, pageNodes);

      // Compile (if necessary) and load the tag files referenced in
      // this compilation unit.
      tfp = new TagFileProcessor();
      tfp.loadTagFiles(this, pageNodes);

      if (log.isLoggable(Level.FINE)) {
        t3 = System.currentTimeMillis();
      }

      // Determine which custom tag needs to declare which scripting vars
      ScriptingVariabler.set(pageNodes, errDispatcher);

      // Optimizations by Tag Plugins
      TagPluginManager tagPluginManager = options.getTagPluginManager();
      tagPluginManager.apply(pageNodes, errDispatcher, pageInfo);

      // Optimization: concatenate contiguous template texts.
      TextOptimizer.concatenate(this, pageNodes);

      // Generate static function mapper codes.
      ELFunctionMapper.map(this, pageNodes);

      // generate servlet .java file
      Generator.generate(writer, this, pageNodes);
      writer.close();
      writer = null;

      // The writer is only used during the compile, dereference
      // it in the JspCompilationContext when done to allow it
      // to be GC'd and save memory.
      ctxt.setWriter(null);

      if (log.isLoggable(Level.FINE)) {
        t4 = System.currentTimeMillis();
        log.fine(
            "Generated "
                + javaFileName
                + " total="
                + (t4 - t1)
                + " generate="
                + (t4 - t3)
                + " validate="
                + (t2 - t1));
      }

    } catch (Exception e) {
      if (writer != null) {
        try {
          writer.close();
          writer = null;
        } catch (Exception e1) {
          // do nothing
        }
      }
      // Remove the generated .java file
      javaCompiler.doJavaFile(false);
      throw e;
    } finally {
      if (writer != null) {
        try {
          writer.close();
        } catch (Exception e2) {
          // do nothing
        }
      }
    }

    // JSR45 Support
    if (!options.isSmapSuppressed()) {
      smapUtil.generateSmap(pageNodes);
    }

    // If any proto type .java and .class files was generated,
    // the prototype .java may have been replaced by the current
    // compilation (if the tag file is self referencing), but the
    // .class file need to be removed, to make sure that javac would
    // generate .class again from the new .java file just generated.
    tfp.removeProtoTypeFiles(ctxt.getClassFileName());
  }
  public void service(HttpServletRequest request, HttpServletResponse response, boolean precompile)
      throws ServletException, IOException, FileNotFoundException {
    try {

      if (ctxt.isRemoved()) {
        throw new FileNotFoundException(jspUri);
      }

      if ((available > 0L) && (available < Long.MAX_VALUE)) {
        response.setDateHeader("Retry-After", available);
        response.sendError(
            HttpServletResponse.SC_SERVICE_UNAVAILABLE,
            Localizer.getMessage("jsp.error.unavailable"));
      }

      if (options.getDevelopment() || firstTime) {
        synchronized (this) {
          ctxt.compile();
        }
      }

      if (reload) {
        getServlet();
      }

      // If a page is to only to be precompiled return.
      if (precompile) {
        return;
      }

      if (theServlet instanceof SingleThreadModel) {
        // sync on the wrapper so that the freshness
        // of the page is determined right before servicing
        synchronized (this) {
          theServlet.service(request, response);
        }
      } else {
        theServlet.service(request, response);
      }

    } catch (UnavailableException ex) {
      String includeRequestUri = (String) request.getAttribute("javax.servlet.include.request_uri");
      if (includeRequestUri != null) {
        // This file was included. Throw an exception as
        // a response.sendError() will be ignored by the
        // servlet engine.
        throw ex;
      } else {
        int unavailableSeconds = ex.getUnavailableSeconds();
        if (unavailableSeconds <= 0) {
          unavailableSeconds = 60; // Arbitrary default
        }
        available = System.currentTimeMillis() + (unavailableSeconds * 1000L);
        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, ex.getMessage());
      }
    } catch (FileNotFoundException ex) {
      String includeRequestUri = (String) request.getAttribute("javax.servlet.include.request_uri");
      if (includeRequestUri != null) {
        // This file was included. Throw an exception as
        // a response.sendError() will be ignored by the
        // servlet engine.
        throw new ServletException(ex);
      } else {
        try {
          response.sendError(HttpServletResponse.SC_NOT_FOUND, ex.getMessage());
        } catch (IllegalStateException ise) {
          log.error(Localizer.getMessage("jsp.error.file.not.found", ex.getMessage()), ex);
        }
      }
    } catch (ServletException ex) {
      throw ex;
    } catch (IOException ex) {
      throw ex;
    } catch (IllegalStateException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new JasperException(ex);
    }
  }
  /**
   * Compile the jsp file into equivalent servlet in .java file
   *
   * @return a smap for the current JSP page, if one is generated, null otherwise
   */
  protected String[] generateJava() throws Exception {

    String[] smapStr = null;

    long t1, t2, t3, t4;

    t1 = t2 = t3 = t4 = 0;

    if (log.isDebugEnabled()) {
      t1 = System.currentTimeMillis();
    }

    // Setup page info area
    pageInfo =
        new PageInfo(new BeanRepository(ctxt.getClassLoader(), errDispatcher), ctxt.getJspFile());

    JspConfig jspConfig = options.getJspConfig();
    JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(ctxt.getJspFile());

    /*
     * If the current uri is matched by a pattern specified in a
     * jsp-property-group in web.xml, initialize pageInfo with those
     * properties.
     */
    if (jspProperty.isELIgnored() != null) {
      pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty.isELIgnored()));
    }
    if (jspProperty.isScriptingInvalid() != null) {
      pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty.isScriptingInvalid()));
    }
    if (jspProperty.getIncludePrelude() != null) {
      pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
    }
    if (jspProperty.getIncludeCoda() != null) {
      pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
    }
    if (jspProperty.isDeferedSyntaxAllowedAsLiteral() != null) {
      pageInfo.setDeferredSyntaxAllowedAsLiteral(
          JspUtil.booleanValue(jspProperty.isDeferedSyntaxAllowedAsLiteral()));
    }
    if (jspProperty.isTrimDirectiveWhitespaces() != null) {
      pageInfo.setTrimDirectiveWhitespaces(
          JspUtil.booleanValue(jspProperty.isTrimDirectiveWhitespaces()));
    }
    // Default ContentType processing is deferred until after the page has
    // been parsed
    if (jspProperty.getBuffer() != null) {
      pageInfo.setBufferValue(jspProperty.getBuffer(), null, errDispatcher);
    }
    if (jspProperty.isErrorOnUndeclaredNamespace() != null) {
      pageInfo.setErrorOnUndeclaredNamespace(
          JspUtil.booleanValue(jspProperty.isErrorOnUndeclaredNamespace()));
    }
    if (ctxt.isTagFile()) {
      try {
        double libraryVersion =
            Double.parseDouble(ctxt.getTagInfo().getTagLibrary().getRequiredVersion());
        if (libraryVersion < 2.0) {
          pageInfo.setIsELIgnored("true", null, errDispatcher, true);
        }
        if (libraryVersion < 2.1) {
          pageInfo.setDeferredSyntaxAllowedAsLiteral("true", null, errDispatcher, true);
        }
      } catch (NumberFormatException ex) {
        errDispatcher.jspError(ex);
      }
    }

    ctxt.checkOutputDir();
    String javaFileName = ctxt.getServletJavaFileName();

    ServletWriter writer = null;
    try {
      /*
       * The setting of isELIgnored changes the behaviour of the parser
       * in subtle ways. To add to the 'fun', isELIgnored can be set in
       * any file that forms part of the translation unit so setting it
       * in a file included towards the end of the translation unit can
       * change how the parser should have behaved when parsing content
       * up to the point where isELIgnored was set. Arghh!
       * Previous attempts to hack around this have only provided partial
       * solutions. We now use two passes to parse the translation unit.
       * The first just parses the directives and the second parses the
       * whole translation unit once we know how isELIgnored has been set.
       * TODO There are some possible optimisations of this process.
       */
      // Parse the file
      ParserController parserCtl = new ParserController(ctxt, this);

      // Pass 1 - the directives
      Node.Nodes directives = parserCtl.parseDirectives(ctxt.getJspFile());
      Validator.validateDirectives(this, directives);

      // Pass 2 - the whole translation unit
      pageNodes = parserCtl.parse(ctxt.getJspFile());

      // Leave this until now since it can only be set once - bug 49726
      if (pageInfo.getContentType() == null && jspProperty.getDefaultContentType() != null) {
        pageInfo.setContentType(jspProperty.getDefaultContentType());
      }

      if (ctxt.isPrototypeMode()) {
        // generate prototype .java file for the tag file
        writer = setupContextWriter(javaFileName);
        Generator.generate(writer, this, pageNodes);
        writer.close();
        writer = null;
        return null;
      }

      // Validate and process attributes - don't re-validate the
      // directives we validated in pass 1
      Validator.validateExDirectives(this, pageNodes);

      if (log.isDebugEnabled()) {
        t2 = System.currentTimeMillis();
      }

      // Collect page info
      Collector.collect(this, pageNodes);

      // Compile (if necessary) and load the tag files referenced in
      // this compilation unit.
      tfp = new TagFileProcessor();
      tfp.loadTagFiles(this, pageNodes);

      if (log.isDebugEnabled()) {
        t3 = System.currentTimeMillis();
      }

      // Determine which custom tag needs to declare which scripting vars
      ScriptingVariabler.set(pageNodes, errDispatcher);

      // Optimizations by Tag Plugins
      TagPluginManager tagPluginManager = options.getTagPluginManager();
      tagPluginManager.apply(pageNodes, errDispatcher, pageInfo);

      // Optimization: concatenate contiguous template texts.
      TextOptimizer.concatenate(this, pageNodes);

      // Generate static function mapper codes.
      ELFunctionMapper.map(pageNodes);

      // generate servlet .java file
      writer = setupContextWriter(javaFileName);
      Generator.generate(writer, this, pageNodes);
      writer.close();
      writer = null;

      // The writer is only used during the compile, dereference
      // it in the JspCompilationContext when done to allow it
      // to be GC'd and save memory.
      ctxt.setWriter(null);

      if (log.isDebugEnabled()) {
        t4 = System.currentTimeMillis();
        log.debug(
            "Generated "
                + javaFileName
                + " total="
                + (t4 - t1)
                + " generate="
                + (t4 - t3)
                + " validate="
                + (t2 - t1));
      }

    } catch (Exception e) {
      if (writer != null) {
        try {
          writer.close();
          writer = null;
        } catch (Exception e1) {
          // do nothing
        }
      }
      // Remove the generated .java file
      File file = new File(javaFileName);
      if (file.exists()) {
        if (!file.delete()) {
          log.warn(
              Localizer.getMessage(
                  "jsp.warning.compiler.javafile.delete.fail", file.getAbsolutePath()));
        }
      }
      throw e;
    } finally {
      if (writer != null) {
        try {
          writer.close();
        } catch (Exception e2) {
          // do nothing
        }
      }
    }

    // JSR45 Support
    if (!options.isSmapSuppressed()) {
      smapStr = SmapUtil.generateSmap(ctxt, pageNodes);
    }

    // If any proto type .java and .class files was generated,
    // the prototype .java may have been replaced by the current
    // compilation (if the tag file is self referencing), but the
    // .class file need to be removed, to make sure that javac would
    // generate .class again from the new .java file just generated.
    tfp.removeProtoTypeFiles(ctxt.getClassFileName());

    return smapStr;
  }
  /** Method used to initialize SecurityManager data. */
  private void initSecurity() {

    // Setup the PermissionCollection for this web app context
    // based on the permissions configured for the root of the
    // web app context directory, then add a file read permission
    // for that directory.
    Policy policy = Policy.getPolicy();
    if (policy != null) {
      try {
        // Get the permissions for the web app context
        String docBase = context.getRealPath("/");
        if (docBase == null) {
          docBase = options.getScratchDir().toString();
        }
        String codeBase = docBase;
        if (!codeBase.endsWith(File.separator)) {
          codeBase = codeBase + File.separator;
        }
        File contextDir = new File(codeBase);
        URL url = contextDir.getCanonicalFile().toURL();
        codeSource = new CodeSource(url, (Certificate[]) null);
        permissionCollection = policy.getPermissions(codeSource);

        // Create a file read permission for web app context directory
        if (!docBase.endsWith(File.separator)) {
          permissionCollection.add(new FilePermission(docBase, "read"));
          docBase = docBase + File.separator;
        } else {
          permissionCollection.add(
              new FilePermission(docBase.substring(0, docBase.length() - 1), "read"));
        }
        docBase = docBase + "-";
        permissionCollection.add(new FilePermission(docBase, "read"));

        // Spec says apps should have read/write for their temp
        // directory. This is fine, as no security sensitive files, at
        // least any that the app doesn't have full control of anyway,
        // will be written here.
        String workDir = options.getScratchDir().toString();
        if (!workDir.endsWith(File.separator)) {
          permissionCollection.add(new FilePermission(workDir, "read,write"));
          workDir = workDir + File.separator;
        }
        workDir = workDir + "-";
        permissionCollection.add(new FilePermission(workDir, "read,write,delete"));

        // Allow the JSP to access org.apache.jasper.runtime.HttpJspBase
        permissionCollection.add(
            new RuntimePermission("accessClassInPackage.org.apache.jasper.runtime"));

        if (parentClassLoader instanceof URLClassLoader) {
          URL[] urls = parentClassLoader.getURLs();
          String jarUrl = null;
          String jndiUrl = null;
          for (int i = 0; i < urls.length; i++) {
            if (jndiUrl == null && urls[i].toString().startsWith("jndi:")) {
              jndiUrl = urls[i].toString() + "-";
            }
            if (jarUrl == null && urls[i].toString().startsWith("jar:jndi:")) {
              jarUrl = urls[i].toString();
              jarUrl = jarUrl.substring(0, jarUrl.length() - 2);
              jarUrl = jarUrl.substring(0, jarUrl.lastIndexOf('/')) + "/-";
            }
          }
          if (jarUrl != null) {
            permissionCollection.add(new FilePermission(jarUrl, "read"));
            permissionCollection.add(new FilePermission(jarUrl.substring(4), "read"));
          }
          if (jndiUrl != null) permissionCollection.add(new FilePermission(jndiUrl, "read"));
        }
      } catch (Exception e) {
        context.log("Security Init for context failed", e);
      }
    }
  }