Package org.w3c.jigsaw.http

Source Code of org.w3c.jigsaw.http.Request

// Request.java
// $Id: Request.java,v 1.37 2003/01/08 12:40:36 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.http ;

import java.io.IOException;
import java.io.InputStream;

import java.net.URL;

import org.w3c.www.mime.MimeParser;

import org.w3c.www.http.ChunkedInputStream;
import org.w3c.www.http.ContentLengthInputStream;
import org.w3c.www.http.HTTP;
import org.w3c.www.http.HttpCredential;
import org.w3c.www.http.HttpEntityMessage;
import org.w3c.www.http.HttpFactory;
import org.w3c.www.http.HttpMessage;
import org.w3c.www.http.HttpParserException;
import org.w3c.www.http.HttpRequestMessage;

import org.w3c.tools.resources.ReplyInterface;
import org.w3c.tools.resources.RequestInterface;
import org.w3c.tools.resources.ResourceFilter;
import org.w3c.tools.resources.ResourceReference;

import org.w3c.tools.codec.Base64Encoder;

/**
* this class extends HttpRequestMessage to cope with HTTP request.
* One subtely here: note how each field acessor <em>never</em> throws an
* exception, but rather is provided with a default value: this is in the hope
* that sometime, HTTP will not require all the parsing it requires right now.
*/

public class Request extends HttpRequestMessage
    implements RequestInterface
{
    /**
     * The URL that means <strong>*</strong> for an <code>OPTIONS</code>
     * method.
     */
    public static URL THE_SERVER = null;

    /**
     * the state of original URL
     */
    public static final String ORIG_URL_STATE =
                                         "org.w3c.jigsaw.http.Request.origurl";

    static {
  try {
      THE_SERVER = new URL("http://your.url.unknown");
  } catch (Exception ex) {
      ex.printStackTrace();
  }
    }

    protected Client      client  = null;
    protected MimeParser  parser  = null;
    protected InputStream in      = null;
    protected boolean     keepcon = true;
    boolean is_proxy = false;

    public void setState(String name, String state) {
  super.setState(name, state);
    }

    /**
     * Fix the target URL of the request, this is the only good time to do so.
     * @param parser The MimeParser
     * @exception HttpParserException if parsing failed.
     * @exception IOException if an IO error occurs.
     */

    public void notifyEndParsing(MimeParser parser)
  throws HttpParserException, IOException
  {
      super.notifyEndParsing(parser);
      String target = getTarget();
      String url    = null;
      // Get rid of the nasty cases(there is a place in hell for someone)
      if ( target.equals("*") ) {
    setURL(THE_SERVER);
    return;
      }
      // Is this a full http URL:
      int    at    = -1;
      int    colon = target.indexOf(':');
      String proto = (colon != -1) ? target.substring(0, colon) : null;
      if ((proto != null) &&
    (proto.equals("http") || proto.equals("ftp"))) {
    // Good we have a full URL:
    try {
        // hugly hack, bug in URL for urls like:
        // http://user:passwd@host:port/file
        if ((at = target.indexOf('@',6)) != -1) {
      String auth = target.substring(colon+3,at);
      int    sep  = -1;
      if ((auth.indexOf('/') == -1) &&
           ((sep = auth.indexOf(':')) != -1)) {
          if (! hasAuthorization()) {
        String username = auth.substring(0,sep);
        String password = auth.substring(sep+1);
        HttpCredential credential =
            HttpFactory.makeCredential("Basic");
        Base64Encoder encoder =
            new Base64Encoder(username+":"+password);
        credential.setAuthParameter("cookie",
                  encoder.processString());
        setAuthorization(credential);
          }
          setURL(new URL(proto+
             "://"+target.substring(at+1)));
      } else {
          setURL(new URL(target));
      }
        } else {
      setURL(new URL(target));
        }
    } catch (Exception ex) {
        throw new HttpParserException("Bogus URL ["+url+"]", this);
    }
      } else {
    try {
        // Do we have a valid host header ?
        String host = getHost();
        if ( host == null ) {
      // If this claims to be 1.1, tell him he's wrong:
      if ((major == 1) && (minor >= 1))
          throw new HttpParserException("No Host Header");
      httpd server = getClient().getServer();
      setURL(new URL("http"
               , server.getHost(), server.getPort()
               , target));
        } else {
      int ic = host.indexOf(':');
      if ( ic < 0 ) {
          setURL(new URL("http", host, target));
      } else {
          setURL(new URL("http"
             , host.substring(0, ic)
             , Integer.parseInt(
                 host.substring(ic+1))
             , target));
      }
        }
    } catch (Exception ex) {
        throw new HttpParserException("Bogus URL ["+url+"]", this);
    }
      }
  }

    // FIXME
    // This guy should also check that the (optional) request stream has been
    // exhausted.

    public boolean canKeepConnection() {
  // HTTP/0.9 doesn't know about keeping connections alive:
  if (( ! keepcon) || (major < 1))
      return false;
  if ( minor >= 1 )
      // HTTP/1.1 keeps connections alive by default
      return hasConnection("close") ? false : true;
  // For HTTP/1.0 check the [proxy] connection header:
  if ( is_proxy )
      return hasProxyConnection("keep-alive");
  else
      return hasConnection("keep-alive");
    }

    private ResourceReference target_resource = null;
    protected void setTargetResource(ResourceReference resource) {
  target_resource = resource;
    }

    /**
     * Get this request target resource.
     * @return An instance of HTTPResource, or <strong>null</strong> if
     * not found.
     */

    public ResourceReference getTargetResource() {
  return target_resource;
    }

    public void setProxy(boolean onoff) {
  is_proxy = onoff;
    }

    public boolean isProxy() {
  return is_proxy;
    }

    public String getURLPath() {
  return url.getFile();
    }

    public void setURLPath(String path) {
  try {
      url = new URL(url, path);
  } catch (Exception ex) {
      ex.printStackTrace();
  }
    }

    public boolean hasContentLength() {
  return hasHeader(H_CONTENT_LENGTH);
    }

    public boolean hasContentType() {
  return hasHeader(H_CONTENT_TYPE);
    }

    public boolean hasAccept() {
  return hasHeader(H_ACCEPT);
    }

    public boolean hasAcceptCharset() {
  return hasHeader(H_ACCEPT_CHARSET);
    }

    public boolean hasAcceptEncoding() {
  return hasHeader(H_ACCEPT_ENCODING);
    }

    public boolean hasAcceptLanguage() {
  return hasHeader(H_ACCEPT_LANGUAGE);
    }

    public boolean hasAuthorization() {
  return hasHeader(H_AUTHORIZATION);
    }

    public boolean hasProxyAuthorization() {
  return hasHeader(H_PROXY_AUTHORIZATION);
    }

    public String getQueryString() {
  return (String) getState("query");
    }

    public boolean hasQueryString() {
  return hasState("query");
    }

    protected boolean internal = false;
    public boolean isInternal() {
  return internal;
    }

    public void setInternal(boolean onoff) {
  this.internal = onoff;
    }

    protected Request original = null;
    public Request getOriginal() {
  return original == null ? this : original ;
    }

    protected ResourceFilter filters[] = null;
    protected int        infilters = -1;
    protected void setFilters(ResourceFilter filters[], int infilters) {
  this.filters   = filters;
  this.infilters = infilters;
    }

    /**
     * Clone this request, in order to launch an internal request.
     * This method can be used to run a request in some given context, defined
     * by an original request. It will preserve all the original information
     * (such as authentication, etc), and will provide a <em>clone</em> of
     * the original request.
     * <p>The original request and its clone differ in the following way:
     * <ul>
     * <li>The clone is marked as <em>internal</em>, which can be tested
     * by the <code>isInternal</code> method.
     * <li>The clone will keep a pointer to the first request that was
     * cloned. This original request can be accessed by the <code>getOriginal
     * </code> method.
     * </ul>
     * <p>To run an internal request, the caller can then use the <code>
     * org.w3c.jigsaw.http.httpd</code> <code>perform</code> method.
     * @return A fresh Request instance, marked as internal.
     */

    public HttpMessage getClone() {
  Request cl = (Request) super.getClone();
  cl.internal = true;
  if ( cl.original == null )
      cl.original = this;
  return cl;
    }

    /**
     * Get this reply entity body.
     * The reply entity body is returned as an InputStream, that the caller
     * has to read to actually get the bytes of the content.
     * @return An InputStream instance. If the reply has no body, the returned
     * input stream will just return <strong>-1</strong> on first read.
     */

    public InputStream getInputStream()
  throws IOException
  {
      if ( in != null )
    return in;
      // Find out which method is used to the length:
      // first, chunked
      String te[] = getTransferEncoding() ;
      if ( te != null ) {
    for (int i = 0 ; i < te.length ; i++) {
        if (te[i].equals("chunked"))
      in = new ChunkedInputStream(
          parser.getInputStream());
    }
      }
      // if not, content-length
      int len = getContentLength();
      if ( (in == null) && (len >= 0) ) {
    in = new ContentLengthInputStream(parser.getInputStream(),len);
      }
      // Handle broken HTTP/1.0 request
      // It is mandatory for 1.1 requests to have been handled above.
      if ((major == 1) && (minor == 0) && (in == null)) {
    String m = getMethod();
    if (m.equals("POST") || m.equals("PUT")) {
        keepcon = false;
        in      = parser.getInputStream();
    }
      }
      return in;
  }

    /**
     * Unescape a HTTP escaped string
     * @param s The string to be unescaped
     * @return the unescaped string.
     */

    public static String unescape (String s) {
  StringBuffer sbuf = new StringBuffer () ;
  int l  = s.length() ;
  int ch = -1 ;
  for (int i = 0 ; i < l ; i++) {
      switch (ch = s.charAt(i)) {
      case '%':
    ch = s.charAt (++i) ;
    int hb = (Character.isDigit ((char) ch)
        ? ch - '0'
        : 10+Character.toLowerCase ((char) ch)-'a') & 0xF ;
    ch = s.charAt (++i) ;
    int lb = (Character.isDigit ((char) ch)
        ? ch - '0'
        : 10+Character.toLowerCase ((char) ch)-'a') & 0xF ;
    sbuf.append ((char) ((hb << 4) | lb)) ;
    break ;
      case '+':
    sbuf.append (' ') ;
    break ;
      default:
    sbuf.append ((char) ch) ;
      }
  }
  return sbuf.toString() ;
    }

    public ReplyInterface makeBadRequestReply() {
  return makeReply(HTTP.BAD_REQUEST);
    }

    /**
     * Make an empty Reply object matching this request version.
     * @param status The status of the reply.
     */

    public Reply makeReply(int status) {
  Reply reply = new Reply(client
        , this
        , getMajorVersion()
        , getMinorVersion()
        , status);
  if ((filters != null) && (infilters > 0))
      reply.setFilters(filters, infilters);
  return reply;
    }

    /**
     * skip the body
     */
    public void skipBody() {
  // don't skip when there is a 100-Continue
  if (getExpect() != null)
      return;
  try {
      InputStream is = getInputStream();
      int avail = is.available();
     
      while (avail > 0) {
    is.skip(avail);
    avail = is.available();
      }
  } catch (Exception ex) {// nothing to skip
  }
    }

    /**
     * Get the client of this request.
     */

    public Client getClient() {
  return client ;
    }

    public Request (Client client, MimeParser parser) {
  super (parser);
  this.parser = parser;
  this.client = client ;
    }


    /**
     * Set this reply entity body.
   * @param is the InputStream instance.
   * USE CAREFULLY : need to be thread-safe
     */
    public void setStream(InputStream is){
  if (is != null)
      this.in = is ;
    }
}
TOP

Related Classes of org.w3c.jigsaw.http.Request

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.