All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.caucho.jsp.Page Maven / Gradle / Ivy

There is a newer version: 4.0.66
Show newest version
/*
 * Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Resin Open Source is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *
 *   Free Software Foundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.jsp;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.caucho.jsp.cfg.JspPropertyGroup;
import com.caucho.make.DependencyContainer;
import com.caucho.server.http.CauchoResponse;
import com.caucho.server.http.ToCharResponseAdapter;
import com.caucho.server.webapp.WebApp;
import com.caucho.util.Base64;
import com.caucho.util.CharBuffer;
import com.caucho.util.QDate;
import com.caucho.vfs.Depend;
import com.caucho.vfs.Dependency;
import com.caucho.vfs.Path;
import com.caucho.vfs.PersistentDependency;

/**
 * Represents a compiled JSP page.
 */
abstract public class Page implements Servlet, ServletConfig, CauchoPage {
  protected static final Logger _caucho_log
    = Logger.getLogger(Page.class.getName());

  private ServletConfig _config;
  private WebApp _webApp;

  private DependencyContainer _depends;
  private ArrayList _cacheDepends;

  protected String _contentType;

  private PageManager.Entry _entry;
  private long _lastModified;
  private String _lastModifiedString;
  private String _etag;
  private QDate _calendar;

  private JspManager _jspManager;

  private boolean _isRecompiling = false;
  private int _useCount;
  private boolean _isDead = true;
  
  public Page()
  {
    _depends = new DependencyContainer();
    _depends.setAsync(false);
  }
  
  public void init(Path path)
    throws ServletException
  {
  }

  public void caucho_init(ServletConfig config)
    throws ServletException
  {
    init(config);
  }

  void _caucho_setContentType(String contentType)
  {
    _contentType = contentType;
  }

  void _caucho_setUpdateInterval(long updateInterval)
  {
    _depends.setCheckInterval(updateInterval);
  }

  void _caucho_setJspManager(JspManager manager)
  {
    _jspManager = manager;
  }

  void _caucho_unload()
  {
    if (_jspManager != null)
      _jspManager.unload(this);
  }

  void _caucho_setEntry(PageManager.Entry entry)
  {
    _entry = entry;
  }

  protected void _caucho_setContentType(String contentType, String encoding)
  {
    if (encoding != null && encoding.equals("ISO-8859-1"))
      encoding = null;

    _contentType = contentType;
  }

  /**
   * Marks the page as uncacheable.
   */
  void _caucho_setUncacheable()
  {
    _cacheDepends = null;
  }

  /**
   * When called treats the JSP page as always modified, i.e. always forcing
   * recompilation.
   */
  protected void _caucho_setAlwaysModified()
  {
    if (_cacheDepends == null) {
      _depends.setModified(true);
    }
  }

  /**
   * When called treats the JSP page as always modified, i.e. always forcing
   * recompilation.
   */
  protected void _caucho_setModified()
  {
    _depends.setModified(true);
  }

  /**
   * Set if the page is never modified.  Some users want to deploy
   * the JSP classes without the JSP source.
   */
  protected void _caucho_setNeverModified(boolean modified)
  {
    _depends.setCheckInterval(-1);
    _depends.setModified(false);
  }

  /**
   * Adds a dependency to the page.
   *
   * @param path the file the JSP page is dependent on.
   */
  protected void _caucho_addDepend(Path path)
  {
    PersistentDependency depend = path.createDepend();
    if (depend instanceof Depend)
      ((Depend) depend).setRequireSource(getRequireSource());

    _caucho_addDepend(depend);
  }

  /**
   * Adds a dependency to the page.
   *
   * @param path the file the JSP page is dependent on.
   */
  protected void _caucho_addDepend(PersistentDependency depend)
  {
    _depends.add(depend);
  }

  /**
   * Adds an array of dependencies to the page.
   */
  protected void _caucho_addDepend(ArrayList dependList)
  {
    if (dependList == null)
      return;

    for (int i = 0; i < dependList.size(); i++)
      _caucho_addDepend(dependList.get(i));
  }

  /**
   * Adds a JSP source dependency.  If the source file changes, the JSP must
   * be recompiled.
   *
   * @param path the path to the file
   * @param lastModified the last modified time
   * @param length the length of the file
   */
  protected void _caucho_addDepend(Path path,
                                   long lastModified,
                                   long length)
  {
    Depend depend = new Depend(path, lastModified, length);
    depend.setRequireSource(getRequireSource());

    _caucho_addDepend(depend);
  }

  public ArrayList _caucho_getDependList()
  {
    return null;
  }

  /**
   * Marks the page as cacheable.
   */
  protected void _caucho_setCacheable()
  {
  }


  /**
   * Adds a single cache dependency.  A cache dependency will cause
   * the page to be rerun, but will not force a recompilation of the JSP.
   *
   * @param path the path to the file
   * @param lastModified the last modified time
   * @param length the length of the file
   */
  protected void _caucho_addCacheDepend(Path path,
                                        long lastModified,
                                        long length)
  {
    if (_cacheDepends == null)
      _cacheDepends = new ArrayList();

    Depend depend = new Depend(path, lastModified, length);

    if (! _cacheDepends.contains(depend))
      _cacheDepends.add(depend);
  }

  /**
   * Adds an array of dependencies which will change the results of
   * running the page.
   *
   * @param depends an array list of Depend
   */
  void _caucho_setCacheable(ArrayList depends)
  {
    _cacheDepends = new ArrayList();
    for (int i = 0; i < depends.size(); i++) {
      Path path = depends.get(i);

      Depend depend = new Depend(path);
      depend.setRequireSource(getRequireSource());

      if (! _cacheDepends.contains(depend))
        _cacheDepends.add(depend);
    }
  }

  /**
   * Returns true if the underlying source has been modified.
   */
  @Override
  public boolean _caucho_isModified()
  {
    return _isDead || _depends.isModified();
  }

  /***
   * Returns true if the underlying source has been modified.
   */
  /*
  public final boolean cauchoIsModified()
  {
    // return (_isDead || _depends.isModified());
    return _caucho_isModified();
  }
  */

  protected HashMap _caucho_getFunctionMap()
  {
    return null;
  }

  /**
   * Returns true if deleting the underlying JSP will force a recompilation.
   */
  private boolean getRequireSource()
  {
    return false;
  }

  /**
   * Initialize the servlet.
   */
  public void init(ServletConfig config)
    throws ServletException
  {
    if (_config != null)
      return;

    _config = config;
    _isDead = false;

    _webApp = (WebApp) config.getServletContext();

    //cauchoIsModified();
    ArrayList depends = _caucho_getDependList();

    for (int i = 0; depends != null && i < depends.size(); i++)
      _depends.add(depends.get(i));

    if (! disableLog() && _caucho_log.isLoggable(Level.FINE))
      _caucho_log.fine(getClass().getName() + " init");
  }

  /**
   * Returns true if initializes.
   */
  public boolean isInit()
  {
    return _config != null;
  }

  /**
   * Returns the Resin webApp.
   */
  public WebApp _caucho_getApplication()
  {
    return _webApp;
  }

  public ServletContext getServletContext()
  {
    return _webApp;
  }

  public String getServletName()
  {
    return _config.getServletName();
  }

  public String getInitParameter(String name)
  {
    return _config.getInitParameter(name);
  }

  public Enumeration getInitParameterNames()
  {
    return _config.getInitParameterNames();
  }

  public void log(String msg)
  {
    _webApp.log(getClass().getName() + ": " + msg);
  }

  public void log(String msg, Throwable cause)
  {
    _webApp.log(getClass().getName() + ": " + msg, cause);
  }

  public String getServletInfo()
  {
    return "A JSP Page";
  }

  boolean disableLog()
  {
    JspPropertyGroup jsp = _webApp.getJsp();

    if (jsp != null)
      return jsp.isDisableLog();

    return true;
  }

  /**
   * Returns this servlet's configuration.
   */
  public ServletConfig getServletConfig()
  {
    return _config;
  }

  /**
   * Initialize the response headers.
   */
  public void _caucho_init(HttpServletRequest req, HttpServletResponse res)
  {
    if (_contentType != null)
      res.setContentType(_contentType);
    else
      res.setContentType("text/html");
  }

  /**
   * Returns the Last-Modified time for use in caching.  If the result
   * is <= 0, last-modified caching is disabled.
   *
   * @return the last modified time.
   */
  public long getLastModified(HttpServletRequest request)
  {
    return _caucho_lastModified();
  }

  /**
   * The default Last-Modified time is just the most recently modified file.
   * For JSP files, this is overwritten to always return 0.
   */
  public long _caucho_lastModified()
  {
    return 0;

    /*
    if (_cacheDepends == null) {
      return 0;
    }
    else {
      return calculateLastModified(_depends, _cacheDepends);
    }
    */
  }

  /**
   * Calculate the last modified time for all the dependencies.  The
   * last modified time is the time of the most recently changed
   * cache or source file.
   *
   * @param depends list of the source file dependencies
   * @param cacheDepends list of the cache dependencies
   *
   * @return the last modified time in milliseconds
   */
  public static long calculateLastModified(ArrayList depends,
                                           ArrayList cacheDepends)
  {
      long lastModified = 0;

      for (int i = 0; i < depends.size(); i++) {
        PersistentDependency dependency = depends.get(i);

        if (dependency instanceof Depend) {
          Depend depend = (Depend) dependency;
          long modified = depend.getLastModified();
          if (lastModified < modified)
            lastModified = modified;
        }
      }

      for (int i = 0; cacheDepends != null && i < cacheDepends.size(); i++) {
        Depend depend = cacheDepends.get(i);
        long modified = depend.getLastModified();
        if (lastModified < modified)
          lastModified = modified;
      }

      return lastModified;
  }

  /**
   * The extended service method creates JavaScript global variables
   * from a property map.
   *
   * 

This method only makes sense for JavaScript templates. To pass * variables to Java templates, use the setAttribute() method of the * request. * * @param properties hashmap of objects to create as JavaScript globals. */ public void pageservice(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { PageManager.Entry entry = _entry; if (entry != null) entry.accessPage(); long lastModified = getLastModified(req); if (lastModified > 0) { if (_calendar == null) _calendar = new QDate(); String etag = _etag; if (lastModified != _lastModified) { CharBuffer cb = new CharBuffer(); cb.append('"'); Base64.encode(cb, lastModified); cb.append('"'); etag = cb.close(); _etag = etag; synchronized (_calendar) { _calendar.setGMTTime(lastModified); _lastModifiedString = _calendar.printDate(); } _lastModified = lastModified; } res.setHeader("ETag", etag); res.setHeader("Last-Modified", _lastModifiedString); String ifMatch = req.getHeader("If-None-Match"); if (etag.equals(ifMatch)) { res.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } String ifModifiedSince = req.getHeader("If-Modified-Since"); if (_lastModifiedString.equals(ifModifiedSince)) { res.sendError(HttpServletResponse.SC_NOT_MODIFIED); return; } } // jsp/0510, jsp/17f? if (res instanceof CauchoResponse) { // JspResponse jspResponse = new JspResponse((CauchoResponse) res); // service(req, jspResponse); service(req, res); } else { // The wrapping is needed to handle the output stream. ToCharResponseAdapter resAdapt = ToCharResponseAdapter.create(res); // resAdapt.setRequest(req); //resAdapt.init(res); try { service(req, resAdapt); } finally { resAdapt.close(); ToCharResponseAdapter.free(resAdapt); } } } protected void setDead() { _isDead = true; } public boolean isDead() { return _isDead; } /** * Starts recompiling. Returns false if the recompiling has already * started or if the page has already been destroyed. */ public boolean startRecompiling() { boolean allowRecompiling; synchronized (this) { allowRecompiling = _isDead || ! _isRecompiling; _isRecompiling = true; } return allowRecompiling; } String getErrorPage() { return null; } /** * Marks the page as used. */ public void _caucho_use() { synchronized (this) { _useCount++; } } /** * Marks the page as free. */ public void _caucho_free() { synchronized (this) { _useCount--; } if (_useCount <= 0) destroy(); } public void destroy() { if (_isDead) return; _isDead = true; /* if (! _isDead) throw new IllegalStateException(); */ _entry = null; Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClass().getClassLoader()); _caucho_log.fine(getClass().getName() + " destroy"); } finally { thread.setContextClassLoader(oldLoader); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy