Package com.planet_ink.coffee_web.http

Source Code of com.planet_ink.coffee_web.http.HTTPException

package com.planet_ink.coffee_web.http;

import java.io.File;
import java.sql.Date;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Logger;

import com.planet_ink.coffee_web.interfaces.DataBuffers;
import com.planet_ink.coffee_web.interfaces.HTTPIOHandler;
import com.planet_ink.coffee_web.interfaces.HTTPOutputConverter;
import com.planet_ink.coffee_web.interfaces.HTTPRequest;
import com.planet_ink.coffee_web.util.CWDataBuffers;
import com.planet_ink.coffee_web.util.CWThread;
import com.planet_ink.coffee_web.util.CWConfig;

/*
Copyright 2012-2014 Bo Zimmerman

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
* An http exception is a throwable class that represents some server response
* that the client didn't expect or prefer, such as a 404, 403, etc..
* They are constructed from HTTPStatus and then tossed up the chain where,
* as an OutputGenerator, they can be used to generate their own full buffer
* output for transmission to the client.
*
* @author Bo Zimmerman
*
*/
public class HTTPException extends Exception
{
  private static final long   serialVersionUID = 9016082700560347737L;

  private final HTTPStatus       status;    // status to return
  private final String         body;    // optional body to send back with the error, usually ""
  private final Map<HTTPHeader,String>errorHeaders = new Hashtable<HTTPHeader,String>(); // any optional/extraneous headers to send back
  private final boolean          isDebugging;
  private final Logger          debugLogger;
  private final CWConfig      config;
  private final static String      EOLN     = HTTPIOHandler.EOLN;
 
  /**
   * Construct with body -- a strange case for now
   * @param status HTTPStatus object
   * @param body the html body
   */
  public HTTPException(HTTPStatus status, String body)
  {
    super(status.description());
    this.body=body;
    this.status = status;
    if(Thread.currentThread() instanceof CWThread)
    {
      this.config=((CWThread)Thread.currentThread()).getConfig();
      this.isDebugging = config.isDebugging();
      this.debugLogger=(isDebugging)?config.getLogger():null;
    }
    else
    {
      this.config=null;
      this.isDebugging=false;
      this.debugLogger=null;
    }
  }

  /**
   * Construct new exception w/o a body
   * @param status the HTTPStatus to return
   */
  public HTTPException(HTTPStatus status)
  {
    super(status.description());
    this.status = status;
    this.body="";
    if(Thread.currentThread() instanceof CWThread)
    {
      this.config=((CWThread)Thread.currentThread()).getConfig();
      this.isDebugging = config.isDebugging();
      this.debugLogger=(isDebugging)?config.getLogger():null;
    }
    else
    {
      this.config=null;
      this.isDebugging=false;
      this.debugLogger=null;
    }
  }

  /**
   * Get the status code object for this exception
   * @return the status code object
   */
  public HTTPStatus getStatus()
  {
    return status;
  }

  /**
   * Get the extraneous headers for this exception
   * For reading or adding-to
   * @return headers map
   */
  public Map<HTTPHeader, String> getErrorHeaders()
  {
    return errorHeaders;
  }
 
  /**
   * Like all HTTPIOHandlers, this class generates its own output buffer.
   * The buffer generated here is typically sent straight to the socket.
   * @param request the request to generate output for
   * @return the client-writable, fully formed output buffer, ready to go
   */
  public DataBuffers generateOutput(HTTPRequest request) throws HTTPException
  {
    final StringBuilder str = new StringBuilder("");
    str.append("HTTP/").append(request.getHttpVer()).append(" ").append(getStatus().getStatusCode()).append(" ").append(getMessage());
    if(isDebugging)
      debugLogger.finer("Response Exception: "+str.toString());
    str.append(EOLN);
    final Map<HTTPHeader,String> headers=getErrorHeaders();
    str.append(HTTPIOHandler.SERVER_HEADER);
    str.append(HTTPIOHandler.CONN_HEADER);
    str.append(HTTPHeader.getKeepAliveHeader());
    str.append(HTTPHeader.DATE.makeLine(HTTPIOHandler.DATE_FORMAT.format(new Date(System.currentTimeMillis()))));
   
    DataBuffers finalBody=null;
    if((body.length()==0)
    &&(status.isAnError())
    &&(config!=null)
    &&(config.getErrorPage().length()>0))
    {
      final File errorFile=config.getFileManager().createFileFromPath(config.getErrorPage());
      DataBuffers fileBytes=null;
      try
      {
        fileBytes=config.getFileCache().getFileData(errorFile, null);
        final MIMEType mimeType=MIMEType.getMIMEType(config.getErrorPage());
        if(mimeType!=null)
        {
          headers.put(HTTPHeader.CONTENT_TYPE, mimeType.getType());
          final Class<? extends HTTPOutputConverter> converterClass=config.getConverters().findConverter(mimeType);
          if(converterClass != null)
          {
            final HTTPOutputConverter converter=converterClass.newInstance();
            finalBody=new CWDataBuffers(converter.convertOutput(config, request, errorFile, status, fileBytes.flushToBuffer()),0,true);
          }
          else
            finalBody=fileBytes;
        }
        else
          finalBody=fileBytes;
      }
      catch(final Exception e)
      {
        if(fileBytes!=null)
          fileBytes.close();
      }
    }
    if(finalBody==null)
    {
      finalBody=new CWDataBuffers(body.getBytes(), 0, true);
    }
    for(final HTTPHeader header : headers.keySet())
    {
      str.append(header.makeLine(headers.get(header)));
    }
    if(finalBody.getLength()>0)
    {
      if(!headers.containsKey(HTTPHeader.CONTENT_TYPE.lowerCaseName()))
        str.append(HTTPHeader.CONTENT_TYPE.makeLine(MIMEType.html.getType()));
      str.append(HTTPHeader.CONTENT_LENGTH.makeLine(finalBody.getLength()));
    }
    else
      str.append(HTTPHeader.CONTENT_LENGTH.makeLine(0));
    str.append(EOLN);
    finalBody.insertTop(str.toString().getBytes(), 0, false);
    return finalBody;
  }
 
  /**
   * Simple cache to save memory and garbage collection time
   */
  private static final Map<HTTPStatus,Map<CWConfig,HTTPException>> factoryExceptions=new Hashtable<HTTPStatus,Map<CWConfig,HTTPException>>();

  /**
   * Static accessor for fetching completely standard-issue exceptions
   * @param status the status of the exception to grab
   * @return a standard issue exception
   */
  public static final HTTPException standardException(final HTTPStatus status)
  {
    Map<CWConfig,HTTPException> xMap=factoryExceptions.get(status);
    final CWConfig config = ((CWThread)Thread.currentThread()).getConfig();
    if(xMap != null)
    {
      if((config != null)&&(xMap.containsKey(config)))
        return xMap.get(config);
    }
    else
    {
      xMap = new Hashtable<CWConfig,HTTPException>();
      factoryExceptions.put(status, xMap);
    }
    final HTTPException exception=new HTTPException(status);
    if(config != null)
    {
      xMap.put(config, exception);
    }
    return exception;
  }
}
TOP

Related Classes of com.planet_ink.coffee_web.http.HTTPException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.