wms-winstone-1.0.5

al transient String X_POWERED_BY_HEADER_VALUE = WinstoneResourceBundle.getInstance().getString("PoweredByHeader");
  private int statusCode;
  private WinstoneRequest req;
  private WebAppConfiguration webAppConfig;
  private WinstoneOutputStream outputStream;
  private PrintWriter outputWriter;
  private final List<String> headers;
  private String explicitEncoding;
  private String implicitEncoding;
  private final List<Cookie> cookies;
  private final Set<Cookie> httpOnlyCookies;
  private Locale locale;
  private String protocol;
  private String reqKeepAliveHeader;
  private Integer errorStatusCode;
  private static final String specialCharacters = "()<>@,;:\\\"/[]?={} \t";
  
  public WinstoneResponse()
  {
    headers = new ArrayList();
    cookies = new ArrayList();
    httpOnlyCookies = new HashSet();
    
    statusCode = 200;
    locale = null;
    explicitEncoding = null;
    protocol = null;
    reqKeepAliveHeader = null;
  }
  
  public void cleanUp()
  {
    req = null;
    webAppConfig = null;
    outputStream = null;
    outputWriter = null;
    headers.clear();
    cookies.clear();
    httpOnlyCookies.clear();
    protocol = null;
    reqKeepAliveHeader = null;
    
    statusCode = 200;
    errorStatusCode = null;
    locale = null;
    explicitEncoding = null;
    implicitEncoding = null;
  }
  
  private String getEncodingFromLocale(Locale locale)
  {
    String localeString = locale.getLanguage() + "_" + locale.getCountry();
    Map<String, String> encMap = webAppConfig.getLocaleEncodingMap();
    logger.debug("Scanning for locale-encoding match: {} in {}", localeString, encMap + "");
    
    String fullMatch = (String)encMap.get(localeString);
    if (fullMatch != null)
    {
      logger.debug("Found locale-encoding match: {}", fullMatch);
      return fullMatch;
    }
    localeString = locale.getLanguage();
    logger.debug("Scanning for locale-encoding match: {} in {}", localeString, encMap + "");
    String match = (String)encMap.get(localeString);
    if (match != null) {
      logger.debug("Found locale-encoding match: {}", match);
    }
    return match;
  }
  
  public void setErrorStatusCode(int statusCode)
  {
    errorStatusCode = new Integer(statusCode);
    this.statusCode = statusCode;
  }
  
  public WinstoneOutputStream getWinstoneOutputStream()
  {
    return outputStream;
  }
  
  public void setOutputStream(WinstoneOutputStream outData)
  {
    outputStream = outData;
  }
  
  public void setWebAppConfig(WebAppConfiguration webAppConfig)
  {
    this.webAppConfig = webAppConfig;
  }
  
  public String getProtocol()
  {
    return protocol;
  }
  
  public void setProtocol(String protocol)
  {
    this.protocol = protocol;
  }
  
  public void extractRequestKeepAliveHeader(WinstoneRequest req)
  {
    reqKeepAliveHeader = req.getHeader("Connection");
  }
  
  public List<String> getHeaders()
  {
    return headers;
  }
  
  public List<Cookie> getCookies()
  {
    return cookies;
  }
  
  public WinstoneRequest getRequest()
  {
    return req;
  }
  
  public void setRequest(WinstoneRequest req)
  {
    this.req = req;
  }
  
  public void startIncludeBuffer()
  {
    outputStream.startIncludeBuffer();
  }
  
  public void finishIncludeBuffer()
    throws IOException
  {
    if (isIncluding())
    {
      if (outputWriter != null) {
        outputWriter.flush();
      }
      outputStream.finishIncludeBuffer();
    }
  }
  
  public void clearIncludeStackForForward()
    throws IOException
  {
    outputStream.clearIncludeStackForForward();
  }
  
  protected static String getCharsetFromContentTypeHeader(String type, StringBuilder remainder)
  {
    if (type == null) {
      return null;
    }
    StringTokenizer st = new StringTokenizer(type, ";");
    String localEncoding = null;
    while (st.hasMoreTokens())
    {
      String clause = st.nextToken().trim();
      if (clause.startsWith("charset="))
      {
        localEncoding = clause.substring(8);
      }
      else
      {
        if (remainder.length() > 0) {
          remainder.append(";");
        }
        remainder.append(clause);
      }
    }
    if ((localEncoding == null) || (!localEncoding.startsWith("\"")) || (!localEncoding.endsWith("\""))) {
      return localEncoding;
    }
    return localEncoding.substring(1, localEncoding.length() - 1);
  }
  
  public void validateHeaders()
  {
    String lengthHeader = getHeader("Content-Length");
    if ((lengthHeader == null) && (statusCode >= 300))
    {
      long bodyBytes = outputStream.getOutputStreamLength();
      if (getBufferSize() > bodyBytes)
      {
        logger.debug("Keep-alive requested but no content length set. Setting to {} bytes", "" + bodyBytes);
        forceHeader("Content-Length", "" + bodyBytes);
        lengthHeader = getHeader("Content-Length");
      }
    }
    forceHeader("Connection", !closeAfterRequest() ? "Keep-Alive" : "Close");
    String contentType = getHeader("Content-Type");
    if (statusCode != 302) {
      if (contentType == null)
      {
        forceHeader("Content-Type", "text/html;charset=" + getCharacterEncoding());
      }
      else if (contentType.startsWith("text/"))
      {
        StringBuilder remainder = new StringBuilder();
        getCharsetFromContentTypeHeader(contentType, remainder);
        forceHeader("Content-Type", remainder.toString() + ";charset=" + getCharacterEncoding());
      }
    }
    if (getHeader("Date") == null) {
      forceHeader("Date", formatHeaderDate(new Date()));
    }
    if (getHeader("X-Powered-By") == null) {
      forceHeader("X-Powered-By", X_POWERED_BY_HEADER_VALUE);
    }
    if (locale != null)
    {
      String lang = locale.getLanguage();
      if ((locale.getCountry() != null) && (!locale.getCountry().equals(""))) {
        lang = lang + "-" + locale.getCountry();
      }
      forceHeader("Content-Language", lang);
    }
    if (req.getWebAppConfig() == null) {
      return;
    }
    HostConfiguration hostConfig = req.getHostGroup().getHostByName(req.getServerName());
    for (Iterator<String> i = req.getCurrentSessionIds().keySet().iterator(); i.hasNext();)
    {
      String prefix = (String)i.next();
      String sessionId = (String)req.getCurrentSessionIds().get(prefix);
      WebAppConfiguration ownerContext = hostConfig.getWebAppByURI(prefix);
      if (ownerContext != null)
      {
        WinstoneSession session = ownerContext.getSessionById(sessionId, Boolean.TRUE.booleanValue());
        if ((session != null) && (session.isNew()))
        {
          session.setIsNew(Boolean.FALSE.booleanValue());
          Cookie cookie = new Cookie(WinstoneSession.SESSION_COOKIE_NAME, session.getId());
          cookie.setMaxAge(-1);
          cookie.setSecure(req.isSecure());
          cookie.setVersion(0);
          cookie.setPath(req.getWebAppConfig().getContextPath().equals("") ? "/" : req.getWebAppConfig().getContextPath());
          cookies.add(cookie);
          
          httpOnlyCookies.add(cookie);
        }
      }
    }
    for (Iterator<String> i = req.getRequestedSessionIds().keySet().iterator(); i.hasNext();)
    {
      String prefix = (String)i.next();
      String sessionId = (String)req.getRequestedSessionIds().get(prefix);
      if (!req.getCurrentSessionIds().containsKey(prefix))
      {
        Cookie cookie = new Cookie(WinstoneSession.SESSION_COOKIE_NAME, sessionId);
        cookie.setMaxAge(0);
        cookie.setSecure(req.isSecure());
        cookie.setVersion(0);
        cookie.setPath(prefix.equals("") ? "/" : prefix);
        cookies.add(cookie);
        
        httpOnlyCookies.add(cookie);
      }
    }
    logger.debug("Headers prepared for writing: {}", "" + headers + "");
  }
  
  public String writeCookie(Cookie cookie)
    throws IOException
  {
    logger.debug("Writing cookie to output: {}", "" + cookie + "");
    StringBuffer out = new StringBuffer();
    if (cookie.getVersion() >= 1) {
      out.append("Set-Cookie").append(": ");
    } else {
      out.append("Set-Cookie").append(": ");
    }
    if (cookie.getVersion() == 0)
    {
      out.append(cookie.getName()).append("=").append(cookie.getValue());
    }
    else
    {
      out.append(cookie.getName()).append("=");
      quote(cookie.getValue(), out);
    }
    if (cookie.getVersion() >= 1)
    {
      out.append("; Version=1");
      if (cookie.getDomain() != null)
      {
        out.append("; Domain=");
        quote(cookie.getDomain(), out);
      }
      if (cookie.getSecure()) {
        out.append("; Secure");
      }
      if (cookie.getMaxAge() >= 0) {
        out.append("; Max-Age=").append(cookie.getMaxAge());
      } else {
        out.append("; Discard");
      }
      if (cookie.getPath() != null)
      {
        out.append("; Path=");
        quote(cookie.getPath(), out);
      }
    }
    else
    {
      if (cookie.getDomain() != null)
      {
        out.append("; Domain=");
        out.append(cookie.getDomain());
      }
      if (cookie.getMaxAge() > 0)
      {
        long expiryMS = System.currentTimeMillis() + 1000L * cookie.getMaxAge();
        String expiryDate = null;
        synchronized (VERSION0_DF)
        {
          expiryDate = VERSION0_DF.format(new Date(expiryMS));
        }
        out.append("; Expires=").append(expiryDate);
      }
      else if (cookie.getMaxAge() == 0)
      {
        String expiryDate = null;
        synchronized (VERSION0_DF)
        {
          expiryDate = VERSION0_DF.format(new Date(5000L));
        }
        out.append("; Expires=").append(expiryDate);
      }
      if (cookie.getPath() != null) {
        out.append("; Path=").append(cookie.getPath());
      }
      if (cookie.getSecure()) {
        out.append("; Secure");
      }
    }
    if (httpOnlyCookies.contains(cookie)) {
      out.append("; HttpOnly");
    }
    return out.toString();
  }
  
  private static String formatHeaderDate(Date dateIn)
  {
    String date = null;
    synchronized (HTTP_DF)
    {
      date = HTTP_DF.format(dateIn);
    }
    return date;
  }
  
  protected static void quote(String value, StringBuffer out)
  {
    if ((value.startsWith("\"")) && (value.endsWith("\"")))
    {
      out.append(value);
    }
    else
    {
      boolean containsSpecial = Boolean.FALSE.booleanValue();
      for (int n = 0; n < value.length(); n++)
      {
        char thisChar = value.charAt(n);
        if ((thisChar < ' ') || (thisChar >= '') || ("()<>@,;:\\\"/[]?={} \t".indexOf(thisChar) != -1))
        {
          containsSpecial = Boolean.TRUE.booleanValue();
          break;
        }
      }
      if (containsSpecial) {
        out.append('"').append(value).append('"');
      } else {
        out.append(value);
      }
    }
  }
  
  public boolean closeAfterRequest()
  {
    String inKeepAliveHeader = reqKeepAliveHeader;
    String outKeepAliveHeader = getHeader("Connection");
    boolean hasContentLength = getHeader("Content-Length") != null;
    if (protocol.startsWith("HTTP/0")) {
      return Boolean.TRUE.booleanValue();
    }
    if ((inKeepAliveHeader == null) && (outKeepAliveHeader == null)) {
      return !hasContentLength ? true : protocol.equals("HTTP/1.0") ? Boolean.TRUE.booleanValue() : false;
    }
    if (outKeepAliveHeader != null) {
      return (outKeepAliveHeader.equalsIgnoreCase("Close")) || (!hasContentLength);
    }
    if (inKeepAliveHeader != null) {
      return (inKeepAliveHeader.equalsIgnoreCase("Close")) || (!hasContentLength);
    }
    return Boolean.FALSE.booleanValue();
  }
  
  public void flushBuffer()
    throws IOException
  {
    if (outputWriter != null) {
      outputWriter.flush();
    }
    try
    {
      outputStream.flush();
    }
    catch (ClientSocketException e) {}
  }
  
  public void setBufferSize(int size)
  {
    outputStream.setBufferSize(size);
  }
  
  public int getBufferSize()
  {
    return (int)outputStream.getBufferSize();
  }
  
  public String getCharacterEncoding()
  {
    String enc = getCurrentEncoding();
    return enc == null ? "ISO-8859-1" : enc;
  }
  
  public void setCharacterEncoding(String encoding)
  {
    if ((outputWriter == null) && (!isCommitted()))
    {
      logger.debug("Setting response character encoding to {}", encoding);
      explicitEncoding = encoding;
      correctContentTypeHeaderEncoding(encoding);
    }
  }
  
  private void correctContentTypeHeaderEncoding(String encoding)
  {
    String contentType = getContentType();
    if (contentType != null)
    {
      StringBuilder remainderHeader = new StringBuilder();
      getCharsetFromContentTypeHeader(contentType, remainderHeader);
      if (remainderHeader.length() != 0) {
        forceHeader("Content-Type", remainderHeader + ";charset=" + encoding);
      }
    }
  }
  
  public String getContentType()
  {
    return getHeader("Content-Type");
  }
  
  public void setContentType(String type)
  {
    setHeader("Content-Type", type);
  }
  
  public Locale getLocale()
  {
    return locale == null ? Locale.getDefault() : locale;
  }
  
  private boolean isIncluding()
  {
    return outputStream.isIncluding();
  }
  
  public void setLocale(Locale loc)
  {
    if (isIncluding()) {
      return;
    }
    if (isCommitted())
    {
      logger.warn("Response.setLocale() ignored, because getWriter already called");
    }
    else
    {
      if ((outputWriter == null) && (explicitEncoding == null))
      {
        String localeEncoding = getEncodingFromLocale(loc);
        if (localeEncoding != null)
        {
          implicitEncoding = localeEncoding;
          correctContentTypeHeaderEncoding(localeEncoding);
        }
      }
      locale = loc;
    }
  }
  
  public ServletOutputStream getOutputStream()
    throws IOException
  {
    logger.debug("Called ServletResponse.getOutputStream()");
    return outputStream;
  }
  
  public PrintWriter getWriter()
    throws IOException
  {
    logger.debug("Called ServletResponse.getWriter()");
    if (outputWriter != null) {
      return outputWriter;
    }
    outputWriter = new WinstoneResponseWriter(outputStream, this);
    return outputWriter;
  }
  
  public boolean isCommitted()
  {
    return outputStream.isCommitted();
  }
  
  public void reset()
  {
    if (!isIncluding())
    {
      resetBuffer();
      statusCode = 200;
      headers.clear();
      cookies.clear();
      httpOnlyCookies.clear();
    }
  }
  
  public void resetBuffer()
  {
    if (!isIncluding())
    {
      if (isCommitted()) {
        throw new IllegalStateException("Response cannot be reset - it is already committed");
      }
      outputStream.setDisregardMode(Boolean.TRUE.booleanValue());
      if (outputWriter != null) {
        outputWriter.flush();
      }
      outputStream.setDisregardMode(Boolean.FALSE.booleanValue());
      outputStream.reset();
    }
  }
  
  public void setContentLength(long len)
  {
    setHeader("Content-Length", Long.toString(len));
  }
  
  public void setContentLength(int len)
  {
    setIntHeader("Content-Length", len);
  }
  
  public void addCookie(Cookie cookie)
  {
    if (!isIncluding()) {
      cookies.add(cookie);
    }
  }
  
  public boolean containsHeader(String name)
  {
    for (String header : headers) {
      if (header.startsWith(name)) {
        return Boolean.TRUE.booleanValue();
      }
    }
    return Boolean.FALSE.booleanValue();
  }
  
  public void addDateHeader(String name, long date)
  {
    addHeader(name, formatHeaderDate(new Date(date)));
  }
  
  public void addIntHeader(String name, int value)
  {
    addHeader(name, "" + value);
  }
  
  public void addHeader(String name, String value)
  {
    if (isIncluding())
    {
      logger.debug("Header ignored inside include - {}: {} ", name, value);
    }
    else if (isCommitted())
    {
      logger.debug("Header ignored after response committed - {}: {} ", name, value);
    }
    else if (value != null)
    {
      if (name.equals("Content-Type"))
      {
        StringBuilder remainderHeader = new StringBuilder();
        String headerEncoding = getCharsetFromContentTypeHeader(value, remainderHeader);
        if (outputWriter != null) {
          value = remainderHeader + ";charset=" + getCharacterEncoding();
        } else if (headerEncoding != null) {
          explicitEncoding = headerEncoding;
        }
      }
      headers.add(name + ": " + value);
    }
  }
  
  public void setDateHeader(String name, long date)
  {
    setHeader(name, formatHeaderDate(new Date(date)));
  }
  
  public void setIntHeader(String name, int value)
  {
    setHeader(name, "" + value);
  }
  
  public void setHeader(String name, String value)
  {
    if (isIncluding())
    {
      logger.debug("Header ignored inside include - {}: {} ", name, value);
    }
    else if (isCommitted())
    {
      logger.debug("Header ignored after response committed - {}: {} ", name, value);
    }
    else
    {
      boolean found = Boolean.FALSE.booleanValue();
      for (int n = 0; n < headers.size(); n++)
      {
        String header = (String)headers.get(n);
        if (header.startsWith(name + ": ")) {
          if (found)
          {
            headers.remove(n);
          }
          else
          {
            if ((name.equals("Content-Type")) && 
              (value != null))
            {
              StringBuilder remainderHeader = new StringBuilder();
              String headerEncoding = getCharsetFromContentTypeHeader(value, remainderHeader);
              if (outputWriter != null) {
                value = remainderHeader + ";charset=" + getCharacterEncoding();
              } else if (headerEncoding != null) {
                explicitEncoding = headerEncoding;
              }
            }
            if (value != null) {
              headers.set(n, name + ": " + value);
            } else {
              headers.remove(n);
            }
            found = Boolean.TRUE.booleanValue();
          }
        }
      }
      if (!found) {
        addHeader(name, value);
      }
    }
  }
  
  private void forceHeader(String name, String value)
  {
    boolean found = Boolean.FALSE.booleanValue();
    for (int n = 0; n < headers.size(); n++)
    {
      String header = (String)headers.get(n);
      if (header.startsWith(name + ": "))
      {
        found = Boolean.TRUE.booleanValue();
        headers.set(n, name + ": " + value);
      }
    }
    if (!found) {
      headers.add(name + ": " + value);
    }
  }
  
  private String getCurrentEncoding()
  {
    if (explicitEncoding != null) {
      return explicitEncoding;
    }
    if (implicitEncoding != null) {
      return implicitEncoding;
    }
    if ((req != null) && (req.getCharacterEncoding() != null)) {
      try
      {
        "0".getBytes(req.getCharacterEncoding());
        return req.getCharacterEncoding();
      }
      catch (UnsupportedEncodingException err)
      {
        return null;
      }
    }
    return null;
  }
  
  public String getHeader(String name)
  {
    for (int n = 0; n < headers.size(); n++)
    {
      String header = (String)headers.get(n);
      if (header.startsWith(name + ": ")) {
        return header.substring(name.length() + 2);
      }
    }
    return null;
  }
  
  public String encodeRedirectURL(String url)
  {
    return url;
  }
  
  public String encodeURL(String url)
  {
    return url;
  }
  
  public int getStatus()
  {
    return statusCode;
  }
  
  public Integer getErrorStatusCode()
  {
    return errorStatusCode;
  }
  
  public void setStatus(int sc)
  {
    if ((!isIncluding()) && (errorStatusCode == null)) {
      statusCode = sc;
    }
  }
  
  public void sendRedirect(String location)
    throws IOException
  {
    if (isIncluding())
    {
      logger.error("Ignoring redirect in include: " + location);
      return;
    }
    if (isCommitted()) {
      throw new IllegalStateException("OutputStream already committed");
    }
    resetBuffer();
    
    StringBuilder fullLocation = new StringBuilder();
    if ((location.startsWith("http://")) || (location.startsWith("https://")))
    {
      fullLocation.append(location);
    }
    else
    {
      if (location.trim().equals(".")) {
        location = "";
      }
      fullLocation.append(req.getScheme()).append("://");
      fullLocation.append(req.getServerName());
      if (((req.getServerPort() != 80) || (!req.getScheme().equals("http"))) && ((req.getServerPort() != 443) || (!req.getScheme().equals("https")))) {
        fullLocation.append(':').append(req.getServerPort());
      }
      if (location.startsWith("/"))
      {
        fullLocation.append(location);
      }
      else
      {
        fullLocation.append(req.getRequestURI());
        int questionPos = fullLocation.toString().indexOf("?");
        if (questionPos != -1) {
          fullLocation.delete(questionPos, fullLocation.length());
        }
        fullLocation.delete(fullLocation.toString().lastIndexOf("/") + 1, fullLocation.length());
        fullLocation.append(location);
      }
    }
    if (req != null) {
      req.discardRequestBody();
    }
    statusCode = 302;
    setHeader("Location", fullLocation.toString());
    setContentLength(0);
    getWriter().flush();
  }
  
  public void sendError(int sc)
    throws IOException
  {
    sendError(sc, null);
  }
  
  public void sendError(int sc, String msg)
    throws IOException
  {
    if (isIncluding())
    {
      logger.error("Error in include: {} {}", "" + sc, msg);
      return;
    }
    logger.debug("Sending error message to browser: code {}, message: {}", "" + sc, msg);
    if ((webAppConfig != null) && (req != null))
    {
      SimpleRequestDispatcher rd = webAppConfig.getErrorDispatcherByCode(req.getRequestURI(), sc, msg, null);
      if (rd != null) {
        try
        {
          rd.forward(req, this);
          return;
        }
        catch (IllegalStateException err)
        {
          throw err;
        }
        catch (IOException err)
        {
          throw err;
        }
        catch (Throwable err)
        {
          if (logger.isWarnEnabled()) {
            logger.warn("Sending error message to browser: code " + rd.getName() + ", message: " + sc, err);
          }
          return;
        }
      }
    }
    if (errorStatusCode == null) {
      statusCode = sc;
    }
    String output = WinstoneResourceBundle.getInstance().getString("WinstoneResponse.ErrorPage", new String[] { sc + "", msg == null ? "" : StringUtils.htmlEscapeBasicMarkup(msg), "", WinstoneResourceBundle.getInstance().getString("ServerVersion"), "" + new Date() });
    
    setContentLength(output.getBytes(getCharacterEncoding()).length);
    Writer out = getWriter();
    out.write(output);
    out.flush();
  }
  
  @Deprecated
  public String encodeRedirectUrl(String url)
  {
    return encodeRedirectURL(url);
  }
  
  @Deprecated
  public String encodeUrl(String url)
  {
    return encodeURL(url);
  }
  
  @Deprecated
  public void setStatus(int sc, String sm)
  {
    setStatus(sc);
  }
}

/* Location:
 * Qualified Name:     net.winstone.core.WinstoneResponse
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package net.winstone.core;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WinstoneResponseWriter
  extends PrintWriter
{
  protected static Logger logger = LoggerFactory.getLogger(WinstoneResponseWriter.class);
  private final WinstoneOutputStream outputStream;
  private final WinstoneResponse response;
  private int bytesBuffered;
  
  public WinstoneResponseWriter(WinstoneOutputStream out, WinstoneResponse response)
    throws UnsupportedEncodingException
  {
    super(new OutputStreamWriter(out, response.getCharacterEncoding()), Boolean.FALSE.booleanValue());
    outputStream = out;
    this.response = response;
    bytesBuffered = 0;
  }
  
  public void write(int c)
  {
    super.write(c);
    appendByteCount("" + (char)c);
  }
  
  public void write(char[] buf, int off, int len)
  {
    super.write(buf, off, len);
    if (buf != null) {
      appendByteCount(new String(buf, off, len));
    }
  }
  
  public void write(String s, int off, int len)
  {
    super.write(s, off, len);
    if (s != null) {
      appendByteCount(s.substring(off, len));
    }
  }
  
  protected void appendByteCount(String input)
  {
    try
    {
      bytesBuffered += input.getBytes(response.getCharacterEncoding()).length;
    }
    catch (IOException err) {}
  }
  
  public void println()
  {
    super.println();
    simulateAutoFlush();
  }
  
  public void flush()
  {
    super.flush();
    bytesBuffered = 0;
  }
  
  protected void simulateAutoFlush()
  {
    String contentLengthHeader = response.getHeader("Content-Length");
    if ((contentLengthHeader != null) && (outputStream.getOutputStreamLength() + bytesBuffered >= Integer.parseInt(contentLengthHeader)))
    {
      logger.debug("Checking for auto-flush of print writer: contentLengthHeader={}, responseBytes={}", contentLengthHeader, outputStream.getOutputStreamLength() + bytesBuffered + "");
      flush();
    }
  }
}

/* Location:
 * Qualified Name:     net.winstone.core.WinstoneResponseWriter
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.1
 */
package net.winstone.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WinstoneSession
  implements HttpSession, Serializable
{
  protected static Logger logger = LoggerFactory.getLogger(WinstoneSession.class);
  private static final long serialVersionUID = 6106594480472753553L;
  public static String SESSION_COOKIE_NAME = "JSESSIONID";
  private String sessionId;
  private WebAppConfiguration webAppConfig;
  private Map<String, Object> sessionData;
  private Set<WinstoneRequest> requestsUsingMe;
  private long createTime;
  private long lastAccessedTime;
  private int maxInactivePeriod;
  private boolean isNew;
  private boolean isInvalidated;
  private HttpSessionAttributeListener[] sessionAttributeListeners;
  private HttpSessionListener[] sessionListeners;
  private HttpSessionActivationListener[] sessionActivationListeners;
  private boolean distributable;
  private Object sessionMonitor = Boolean.TRUE;
  
  public WinstoneSession(String sessionId)
  {
    this.sessionId = sessionId;
    sessionData = new Hashtable();
    requestsUsingMe = Collections.synchronizedSet(new HashSet());
    createTime = System.currentTimeMillis();
    isNew = Boolean.TRUE.booleanValue();
    isInvalidated = Boolean.FALSE.booleanValue();
  }
  
  public void setWebAppConfiguration(WebAppConfiguration webAppConfig)
  {
    this.webAppConfig = webAppConfig;
    distributable = webAppConfig.isDistributable();
  }
  
  public void sendCreatedNotifies()
  {
    for (int n = 0; n < sessionListeners.length; n++)
    {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      sessionListeners[n].sessionCreated(new HttpSessionEvent(this));
      Thread.currentThread().setContextClassLoader(cl);
    }
  }
  
  public void setSessionActivationListeners(HttpSessionActivationListener[] listeners)
  {
    sessionActivationListeners = listeners;
  }
  
  public void setSessionAttributeListeners(HttpSessionAttributeListener[] listeners)
  {
    sessionAttributeListeners = listeners;
  }
  
  public void setSessionListeners(HttpSessionListener[] listeners)
  {
    sessionListeners = listeners;
  }
  
  public void setLastAccessedDate(long time)
  {
    lastAccessedTime = time;
  }
  
  public void setIsNew(boolean isNew)
  {
    this.isNew = isNew;
  }
  
  public void addUsed(WinstoneRequest request)
  {
    requestsUsingMe.add(request);
  }
  
  public void removeUsed(WinstoneRequest request)
  {
    requestsUsingMe.remove(request);
  }
  
  public boolean isUnusedByRequests()
  {
    return requestsUsingMe.isEmpty();
  }
  
  public boolean isExpired()
  {
    long nowDate = System.currentTimeMillis();
    long maxInactive = getMaxInactiveInterval() * 1000;
    return (maxInactive > 0L) && (nowDate - lastAccessedTime > maxInactive);
  }
  
  public Object getAttribute(String name)
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    Object att = null;
    synchronized (sessionMonitor)
    {
      att = sessionData.get(name);
    }
    return att;
  }
  
  public Enumeration<String> getAttributeNames()
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    Enumeration<String> names = null;
    synchronized (sessionMonitor)
    {
      names = Collections.enumeration(sessionData.keySet());
    }
    return names;
  }
  
  public void setAttribute(String name, Object value)
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    if ((distributable) && (value != null) && (!(value instanceof Serializable))) {
      throw new IllegalArgumentException("Web application is marked distributable, but session object " + name + " (class " + value.getClass().getName() + ") does not extend java.io.Serializable - this variable will be ignored if the session is tranferred");
    }
    if ((value instanceof HttpSessionBindingListener))
    {
      HttpSessionBindingListener hsbl = (HttpSessionBindingListener)value;
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      hsbl.valueBound(new HttpSessionBindingEvent(this, name, value));
      Thread.currentThread().setContextClassLoader(cl);
    }
    Object oldValue = null;
    synchronized (sessionMonitor)
    {
      oldValue = sessionData.get(name);
      if (value == null) {
        sessionData.remove(name);
      } else {
        sessionData.put(name, value);
      }
    }
    if ((oldValue instanceof HttpSessionBindingListener))
    {
      HttpSessionBindingListener hsbl = (HttpSessionBindingListener)oldValue;
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      hsbl.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
      Thread.currentThread().setContextClassLoader(cl);
    }
    if (oldValue != null) {
      for (int n = 0; n < sessionAttributeListeners.length; n++)
      {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
        sessionAttributeListeners[n].attributeReplaced(new HttpSessionBindingEvent(this, name, oldValue));
        Thread.currentThread().setContextClassLoader(cl);
      }
    } else {
      for (int n = 0; n < sessionAttributeListeners.length; n++)
      {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
        sessionAttributeListeners[n].attributeAdded(new HttpSessionBindingEvent(this, name, value));
        Thread.currentThread().setContextClassLoader(cl);
      }
    }
  }
  
  public void removeAttribute(String name)
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    Object value = null;
    synchronized (sessionMonitor)
    {
      value = sessionData.get(name);
      sessionData.remove(name);
    }
    if ((value instanceof HttpSessionBindingListener))
    {
      HttpSessionBindingListener hsbl = (HttpSessionBindingListener)value;
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      hsbl.valueUnbound(new HttpSessionBindingEvent(this, name));
      Thread.currentThread().setContextClassLoader(cl);
    }
    if (value != null) {
      for (int n = 0; n < sessionAttributeListeners.length; n++)
      {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
        sessionAttributeListeners[n].attributeRemoved(new HttpSessionBindingEvent(this, name, value));
        Thread.currentThread().setContextClassLoader(cl);
      }
    }
  }
  
  public long getCreationTime()
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    return createTime;
  }
  
  public long getLastAccessedTime()
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    return lastAccessedTime;
  }
  
  public String getId()
  {
    return sessionId;
  }
  
  public int getMaxInactiveInterval()
  {
    return maxInactivePeriod;
  }
  
  public void setMaxInactiveInterval(int interval)
  {
    maxInactivePeriod = interval;
  }
  
  public boolean isNew()
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    return isNew;
  }
  
  public ServletContext getServletContext()
  {
    return webAppConfig;
  }
  
  public void invalidate()
  {
    if (isInvalidated) {
      throw new IllegalStateException("Session has been invalidated");
    }
    for (int n = sessionListeners.length - 1; n >= 0; n--)
    {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      sessionListeners[n].sessionDestroyed(new HttpSessionEvent(this));
      Thread.currentThread().setContextClassLoader(cl);
    }
    List<String> keys = new ArrayList(sessionData.keySet());
    for (Iterator<String> i = keys.iterator(); i.hasNext();) {
      removeAttribute((String)i.next());
    }
    synchronized (sessionMonitor)
    {
      sessionData.clear();
    }
    isInvalidated = Boolean.TRUE.booleanValue();
    webAppConfig.removeSessionById(sessionId);
  }
  
  public void passivate()
  {
    for (int n = 0; n < sessionActivationListeners.length; n++)
    {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(webAppConfig.getLoader());
      sessionActivationListeners[n].sessionWillPassivate(new HttpSessionEvent(this));
      Thread.currentThread().setContextClassLoader(cl);
    }
    synchronized (sessionMonitor)
    {
      sessionData.clear();
    }
    webAppConfig.removeSessionById(sessionId);
  }
  
  public void activate(WebAppConfiguration webAppConfig)
  {
    this.webAppConfig = webAppConfig;
    webAppConfig.setSessionListeners(this);
    for (int n = 0; n < sessionActivationListeners.length; n++)
    {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
      sessionActivationListeners[n].sessionDidActivate(new HttpSessionEvent(this));
      Thread.currentThread().setContextClassLoader(cl);
    }
  }
  
  public void saveToTemp()
  {
    File toDir = getSessionTempDir(webAppConfig);
    synchronized (sessionMonitor)
    {
      OutputStream out = null;
      ObjectOutputStream objOut = null;
      try
      {
        File toFile = new File(toDir, sessionId + ".ser");
        out = new FileOutputStream(toFile, Boolean.FALSE.booleanValue());
        objOut = new ObjectOutputStream(out);
        objOut.writeObject(this);
        if (objOut != null) {
          try
          {
            objOut.close();
          }
          catch (IOException err) {}
        }
        if (out != null) {
          try
          {
            out.close();
          }
          catch (IOException err) {}
        }
      }
      catch (IOException err)
      {
        logger.error("Error saving the session to temp space. Error:", err);
      }
      finally
      {
        if (objOut != null) {
          try
          {
            objOut.close();
          }
          catch (IOException err) {}
        }
        if (out != null) {
          try
          {
            out.close();
          }
          catch (IOException err) {}
        }
      }
    }
  }
  
  public static File getSessionTempDir(WebAppConfiguration webAppConfig)
  {
    File tmpDir = (File)webAppConfig.getAttribute("javax.servlet.context.tempdir");
    File sessionsDir = new File(tmpDir, "WEB-INF" + File.separator + "winstoneSessions");
    if (!sessionsDir.exists()) {
      sessionsDir.mkdirs();
    }
    return sessionsDir;
  }
  
  public static void loadSessions(WebAppConfiguration webAppConfig)
  {
    int expiredCount = 0;
    
    File tempDir = getSessionTempDir(webAppConfig);
    File[] possibleSessionFiles = tempDir.listFiles();
    for (int n = 0; n < possibleSessionFiles.length; n++) {
      if (possibleSessionFiles[n].getName().endsWith(".ser"))
      {
        InputStream in = null;
        ObjectInputStream objIn = null;
        try
        {
          in = new FileInputStream(possibleSessionFiles[n]);
          objIn = new ObjectInputStream(in);
          WinstoneSession session = (WinstoneSession)objIn.readObject();
          session.setWebAppConfiguration(webAppConfig);
          webAppConfig.setSessionListeners(session);
          if (session.isExpired())
          {
            session.invalidate();
            expiredCount++;
          }
          else
          {
            webAppConfig.addSession(session.getId(), session);
            logger.debug("Successfully restored session id {} from temp space", session.getId());
          }
        }
        catch (Throwable err)
        {
          logger.error("Error loading session from temp space - skipping. Error:", err);
        }
        finally
        {
          if (objIn != null) {
            try
            {
              objIn.close();
            }
            catch (IOException err) {}
          }
          if (in != null) {
            try
            {
              in.close();
            }
            catch (IOException err) {}
          }
          possibleSessionFiles[n].delete();
        }
      }
    }
    if (expiredCount > 0) {
      logger.debug(expiredCount + " Session(s) has been invalidated");
    }
  }
  
  private void writeObject(ObjectOutputStream out)
    throws IOException
  {
    out.writeUTF(sessionId);
    out.writeLong(createTime);
    out.writeLong(lastAccessedTime);
    out.writeInt(maxInactivePeriod);
    out.writeBoolean(isNew);
    out.writeBoolean(distributable);
    
    Map<String, Object> copy = new HashMap(sessionData);
    Set<String> keys = new HashSet(copy.keySet());
    for (Iterator<String> i = keys.iterator(); i.hasNext();)
    {
      String key = (String)i.next();
      if (!(copy.get(key) instanceof Serializable)) {
        logger.warn("Web application is marked distributable, but session object {} (class {}) does not extend java.io.Serializable - this variable is being ignored by session transfer", key, copy.get(key).getClass().getName());
      }
      copy.rem
1 2 3 4 5 6 7 8 9 10 11 12 13 14

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd