예제 #1
0
  public Servlet getServlet() throws ServletException {
    // DCL on 'reload' requires that 'reload' be volatile
    // (this also forces a read memory barrier, ensuring the
    // new servlet object is read consistently)
    if (reload) {
      synchronized (this) {
        // Synchronizing on jsw enables simultaneous loading
        // of different pages, but not the same page.
        if (reload) {
          // This is to maintain the original protocol.
          destroy();

          final Servlet servlet;

          try {
            InstanceManager instanceManager = InstanceManagerFactory.getInstanceManager(config);
            servlet = (Servlet) instanceManager.newInstance(ctxt.getFQCN(), ctxt.getJspLoader());
          } catch (IllegalAccessException e) {
            throw new JasperException(e);
          } catch (InstantiationException e) {
            throw new JasperException(e);
          } catch (Exception e) {
            throw new JasperException(e);
          }

          servlet.init(config);

          if (!firstTime) {
            ctxt.getRuntimeContext().incrementJspReloadCount();
          }

          theServlet = servlet;
          reload = false;
          // Volatile 'reload' forces in order write of 'theServlet' and new servlet object
        }
      }
    }
    return theServlet;
  }
예제 #2
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);
    }
  }
예제 #3
0
  /**
   * Determine if a compilation is necessary by checking the time stamp of the JSP page with that of
   * the corresponding .class or .java file. If the page has dependencies, the check is also
   * extended to its dependeants, and so on. This method can by overidden by a subclasses of
   * Compiler.
   *
   * @param checkClass If true, check against .class file, if false, check against .java file.
   */
  public boolean isOutDated(boolean checkClass) {

    String jsp = ctxt.getJspFile();

    if (jsw != null && (ctxt.getOptions().getModificationTestInterval() > 0)) {

      if (jsw.getLastModificationTest() + (ctxt.getOptions().getModificationTestInterval() * 1000)
          > System.currentTimeMillis()) {
        return false;
      } else {
        jsw.setLastModificationTest(System.currentTimeMillis());
      }
    }

    long jspRealLastModified = 0;
    // START PWC 6468930
    File targetFile;

    if (checkClass) {
      targetFile = new File(ctxt.getClassFileName());
    } else {
      targetFile = new File(ctxt.getServletJavaFileName());
    }

    // Get the target file's last modified time. File.lastModified()
    // returns 0 if the file does not exist.
    long targetLastModified = targetFile.lastModified();

    // Check cached class file
    if (checkClass) {
      JspRuntimeContext rtctxt = ctxt.getRuntimeContext();
      String className = ctxt.getFullClassName();
      long cachedTime = rtctxt.getBytecodeBirthTime(className);
      if (cachedTime > targetLastModified) {
        targetLastModified = cachedTime;
      } else {
        // Remove from cache, since the bytecodes from the file is more
        // current, so that JasperLoader won't load the cached version
        rtctxt.setBytecode(className, null);
      }
    }

    if (targetLastModified == 0L) return true;

    // Check if the jsp exists in the filesystem (instead of a jar
    // or a remote location). If yes, then do a File.lastModified()
    // to determine its last modified time. This is more performant
    // (fewer stat calls) than the ctxt.getResource() followed by
    // openConnection(). However, it only works for file system jsps.
    // If the file has indeed changed, then need to call URL.OpenConnection()
    // so that the cache loads the latest jsp file
    if (jsw != null) {
      File jspFile = jsw.getJspFile();
      if (jspFile != null) {
        jspRealLastModified = jspFile.lastModified();
      }
    }
    if (jspRealLastModified == 0 || targetLastModified < jspRealLastModified) {
      // END PWC 6468930
      try {
        URL jspUrl = ctxt.getResource(jsp);
        if (jspUrl == null) {
          ctxt.incrementRemoved();
          return false;
        }
        URLConnection uc = jspUrl.openConnection();
        jspRealLastModified = uc.getLastModified();
        uc.getInputStream().close();
      } catch (Exception e) {
        e.printStackTrace();
        return true;
      }
      // START PWC 6468930
    }
    // END PWC 6468930
    /* PWC 6468930
    long targetLastModified = 0;
    File targetFile;

    if( checkClass ) {
        targetFile = new File(ctxt.getClassFileName());
    } else {
        targetFile = new File(ctxt.getServletJavaFileName());
    }

    if (!targetFile.exists()) {
        return true;
    }

    targetLastModified = targetFile.lastModified();
    */
    if (checkClass && jsw != null) {
      jsw.setServletClassLastModifiedTime(targetLastModified);
    }

    if (targetLastModified < jspRealLastModified) {
      // Remember JSP mod time
      jspModTime = jspRealLastModified;
      if (log.isLoggable(Level.FINE)) {
        log.fine("Compiler: outdated: " + targetFile + " " + targetLastModified);
      }
      return true;
    }

    // determine if source dependent files (e.g. includes using include
    // directives) have been changed.
    if (jsw == null) {
      return false;
    }

    List depends = jsw.getDependants();
    if (depends == null) {
      return false;
    }

    Iterator it = depends.iterator();
    while (it.hasNext()) {
      String include = (String) it.next();
      try {
        URL includeUrl = ctxt.getResource(include);
        if (includeUrl == null) {
          return true;
        }

        URLConnection includeUconn = includeUrl.openConnection();
        long includeLastModified = includeUconn.getLastModified();
        includeUconn.getInputStream().close();

        if (includeLastModified > targetLastModified) {
          // START GlassFish 750
          if (include.endsWith(".tld")) {
            ctxt.clearTaglibs();
            ctxt.clearTagFileJarUrls();
          }
          // END GlassFish 750
          return true;
        }
      } catch (Exception e) {
        e.printStackTrace();
        return true;
      }
    }

    return false;
  }
예제 #4
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);
  }