home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / net / www / http / HttpClient.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  12.7 KB  |  443 lines

  1. /*
  2.  * @(#)HttpClient.java    1.53 95/12/05 Jonathan Payne
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.net.www.http;
  21.  
  22. import java.io.*;
  23. import java.net.*;
  24. import java.util.*;
  25. import sun.net.NetworkClient;
  26. import sun.net.ProgressData;
  27. import sun.net.TelnetInputStream;
  28. import sun.net.www.MessageHeader;
  29.  
  30. /**
  31.  * @version 1.47 22 Aug 1995
  32.  * @author Jonathan Payne
  33.  */
  34. public final class HttpClient extends NetworkClient {
  35.     static final boolean    debug = false;
  36.  
  37.     static final String    userAgentString = 
  38.         "User-Agent: " + System.getProperty("http.agent", 
  39.               "Java" + System.getProperty("java.version")) + "\r\n";
  40.  
  41.     static final String acceptString
  42.     = "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n";
  43.  
  44.     /** Default port number for http daemons - this is not
  45.         a registered service as far as I can tell. */
  46.     static final int    httpPortNumber = 80;
  47.  
  48.     public static boolean   useProxyForFirewall = Boolean.getBoolean("firewallSet");
  49.     public static String    firewallProxyHost = System.getProperty("firewallHost");
  50.     public static int        firewallProxyPort = Integer.getInteger("firewallPort", 80).intValue();
  51.  
  52.     public static boolean   useProxyForCaching = Boolean.getBoolean("proxySet");
  53.     public static String    cachingProxyHost = System.getProperty("proxyHost", "sunweb.ebay");
  54.     public static int        cachingProxyPort = Integer.getInteger("proxyPort", 80).intValue();
  55.     /* instance-specific proxy fields override the static fields if */
  56.     /* set. */
  57.     private String        proxy = null;
  58.     private int            proxyPort = -1;
  59.  
  60.     /* request essentially succeeded */
  61.     public static final int    OK = 200;
  62.     public static final int    CREATED = 201;
  63.     public static final int    ACCEPTED = 202;
  64.     public static final int    PARTIAL = 203;
  65.  
  66.     /* document redirection */
  67.     public static final int    MOVED = 301;
  68.     public static final int    FOUND = 302;
  69.     public static final int    METHOD = 303;
  70.  
  71.     /* errors */
  72.     public static final int    BAD = 400;
  73.     public static final int    UNAUTHORIZED = 401;
  74.     public static final int    PAYMENT_REQUIRED = 402;
  75.     public static final int    FORBIDDEN = 403;
  76.     public static final int    NOT_FOUND = 404;
  77.     public static final int    INTERNAL_ERROR = 500;
  78.     public static final int    NOT_IMPLEMENTED = 501;
  79.  
  80.     int            status;
  81.     MessageHeader    mimeHeader = null;
  82.     boolean        usingProxy = false;
  83.     String        host;
  84.     String        authentication = null;
  85.  
  86.  
  87.     /** Url being fetched. */
  88.     URL            url;
  89.  
  90.     public synchronized void openServer(String host, int port) throws UnauthorizedHttpRequestException, UnknownHostException, SocketException, IOException {
  91.     this.host = host;
  92.     boolean AllIsWell = false;
  93.     String   s;
  94.  
  95. //    ProgressData.pdata.register(url);
  96.     try {
  97.  
  98.         if (debug) {
  99.         System.out.println("openServer " + host + ":" + port);
  100.         }
  101.         SecurityManager security = System.getSecurityManager();
  102.         if (security != null) {
  103.         security.checkConnect(host, port);
  104.         }
  105.         /*
  106.         if ((s = Firewall.verifyAccess(host, port)) != null) {
  107.         String msg = "Applet at " + s + " attempted illegal URL access: ";
  108.  
  109.         msg = msg + url.toExternalForm();
  110.         Firewall.securityError(msg);
  111.         return;
  112.         }
  113.         */
  114.         
  115.         if (url.getProtocol().equals("http")) {
  116.         if (useProxyForCaching) {
  117.             /* This would only fail if the specified host is
  118.                unknown to the proxy, e.g., a local host was
  119.                specified that isn't exported to the net which
  120.                the proxy is on.  In that case, we keep trying
  121.                just in case the host is known locally. */        
  122.             super.openServer(cachingProxyHost, cachingProxyPort);
  123.             usingProxy = true;
  124.             return;
  125.         }
  126.         try {
  127.             super.openServer(host, port);
  128.         } catch (UnknownHostException e) {
  129.             if (useProxyForFirewall) {
  130.             if (proxy == null) {
  131.                 super.openServer(firewallProxyHost,firewallProxyPort);
  132.             } else {
  133.                 super.openServer(proxy, proxyPort);
  134.             }
  135.             usingProxy = true;
  136.             } else {
  137.             throw e;
  138.             }
  139.         }
  140.  
  141.         // do the same thing if we got a SocketException --
  142.         // that is, send the request to the proxy
  143.         catch (SocketException se) {
  144.             if (useProxyForFirewall) {
  145.             if (proxy == null) {
  146.                 super.openServer(firewallProxyHost,firewallProxyPort);
  147.             } else {
  148.                 super.openServer(proxy, proxyPort);
  149.             }
  150.             usingProxy = true;
  151.             } else {
  152.             throw se;
  153.             }
  154.         }
  155.  
  156.         } else {
  157.         // we're opening some other kind of url, most likely an
  158.         // ftp url.
  159.         if (proxy == null) {
  160.             super.openServer(firewallProxyHost,firewallProxyPort);
  161.         } else {
  162.             super.openServer(proxy, proxyPort);
  163.         }
  164.         usingProxy = true;
  165.         }
  166.         AllIsWell = true;
  167.     } finally {
  168. //        if (!AllIsWell)
  169. //        ProgressData.pdata.unregister(url);
  170.     }
  171.     }
  172.  
  173.     /** Parse the first line of the HTTP request.  It usually looks
  174.     something like: "HTTP/1.0 <number> comment\r\n". */
  175.  
  176.     protected void getRequestStatus(String response, String name)
  177.     throws UnauthorizedHttpRequestException, FileNotFoundException {
  178.     if (debug) {
  179.         System.out.println(response);
  180.     }
  181.     if (response.startsWith("HTTP/1.0 ")) {
  182.         status = Integer.parseInt(response.substring(9, 12));
  183.     } else {
  184.         status = -1;
  185.     }
  186.     switch (status) {
  187.     case UNAUTHORIZED:
  188.         throw new UnauthorizedHttpRequestException(url, this);
  189.  
  190.     case BAD:
  191.     case PAYMENT_REQUIRED:
  192.     case INTERNAL_ERROR:
  193.     case NOT_IMPLEMENTED:
  194. //        throw new Exception("HTTP request failed: " + response);
  195. //        fall through
  196.     case FORBIDDEN:
  197.     case NOT_FOUND:
  198.         //System.out.println("Throwing file not found");
  199.         throw new FileNotFoundException(response + " -- " + name);
  200.     }
  201.     }
  202.  
  203.     public String getURLFile(URL u) {
  204.     if (usingProxy) {
  205.         String result = u.getProtocol() + "://" + u.getHost();
  206.         if (u.getPort() != -1) {
  207.         result += ":" + u.getPort();
  208.         }
  209.         return result + u.getFile();
  210.     } else {
  211.         return u.getFile();
  212.     }
  213.     }
  214.  
  215.     public void processRequest(String name)
  216.     throws UnauthorizedHttpRequestException, IOException {
  217.     /*
  218.      * Read until 200 bytes or EOF, or until we hit a blank
  219.      * line, whichever occurs first, looking for the string
  220.      * "HTTP/1.0" at the beginning of the line.  This is not
  221.      * strictly speaking necessary from the spec., but it is
  222.      * necessary since Netscape does it and therefore people
  223.      * have written their pages this way, broken as it is.  An
  224.      * example is mumble:80 which sometimes spews the line
  225.      * "Trying..." before returning a valid HTTP reply.
  226.      *
  227.      * In any case we always retain the first line of the
  228.      * response because it is useful if the server turns out to
  229.      * be a pre-HTTP1.0 server.
  230.      */
  231.  
  232.     BufferedInputStream bis = (BufferedInputStream) serverInput;
  233.     String status_response = null;
  234.     String firstLine = null;
  235.  
  236.     bis.mark(200);
  237.     DataInputStream dis =
  238.         new DataInputStream(new TelnetInputStream(serverInput, false));
  239.  
  240.     while (true) {
  241.         String  line = dis.readLine();
  242.  
  243.         if (debug) {
  244.         System.err.println((line == null) ? "<null>" : line);
  245.         }
  246.  
  247.         if (firstLine == null) {
  248.         if (line == null) {
  249.             throw new SocketException("Unexpected EOF");
  250.         }
  251.         firstLine = new String(line);
  252.         }
  253.         if (line == null || line.length() == 0) /* end of header */
  254.         break;
  255.         if (line.startsWith("HTTP/1.0")) {
  256.         status_response = new String(line);
  257.         if (!firstLine.startsWith("HTTP/1.0")) {
  258.             System.err.println("Warning: The first line from "+url+
  259.                        " was not HTTP/1.0 compliant.");
  260.             System.err.println("         '"+firstLine+"'");
  261.         }
  262.         break;
  263.         }
  264.     }
  265.  
  266.     bis.reset();
  267.  
  268.     try {
  269.         try {
  270.         if (status_response != null) {
  271.         byte buf[] = new byte[10];
  272.         int count = 0;
  273.         int c;
  274.  
  275.         /* Even if the request status indicates error, we parse
  276.            the mime header in case there is something in the mime
  277.            header we need in order to recover from the error. E.g.,
  278.            authentication. */
  279.         try {
  280.             getRequestStatus(status_response, name);
  281.         } finally {
  282.             mimeHeader = new MessageHeader(serverInput);
  283.         }
  284.         } else {
  285.         String    line = firstLine;
  286.  
  287.         if (line == null || line.length() == 0) {
  288.             throw new SocketException("Unexpected EOF");
  289.         } else if (line.indexOf("hostname unknown") != -1) {
  290.             throw new UnknownHostException(host);
  291.         } else if (line.indexOf("refused") != -1
  292.                || line.startsWith("</BODY>")) {
  293.             /* REMIND: </BODY> seems to be what the proxy on
  294.                sunweb.ebay spits back for connection refused,
  295.                but I am just hoping that *some* proxy server
  296.                indicates "connection refused" with the string
  297.                "refused" some place in the error message. */
  298.             throw new SocketException("Connection refused");
  299.         }
  300.         }
  301.         } finally {
  302. //        ProgressData.pdata.connected(url);
  303.         }
  304.     } catch (UnauthorizedHttpRequestException e) {
  305.         /* don't close server, because we might let it
  306.            fall through to get whatever message is behind
  307.            the authentication, assuming the authentication
  308.            fails */
  309.         throw e;
  310.     } catch (Exception e) {
  311.         String cl = getHeaderField("content-length");
  312.         int len = 0;
  313.         if (cl == null || (len = Integer.parseInt(cl)) == 0) {
  314.         try {
  315.             closeServer();
  316.         } catch(Throwable e2) {}
  317.         throw (e instanceof IOException
  318.                ? (IOException) e : new IOException(e.toString()));
  319.         }
  320.     }
  321.     }
  322.  
  323.     /** Close an open connection to the server. */
  324.     public void closeServer() {
  325.     if (url != null) {
  326. //        ProgressData.pdata.unregister(url);
  327.         this.url = null;
  328.     }
  329.     try {
  330.     super.closeServer();
  331.     } catch(Throwable e) {}
  332.     }
  333.  
  334.     public MessageHeader getMimeHeader() {
  335.     return mimeHeader;
  336.     }
  337.  
  338.     public String getHeaderField(String fieldName) {
  339.     return mimeHeader != null
  340.         ? mimeHeader.findValue(fieldName)
  341.         : null;
  342.     }
  343.  
  344.     public int getStatus() {
  345.     return status;
  346.     }
  347.  
  348.     public InputStream getInputStream() {
  349.     return serverInput;
  350.     }
  351.  
  352.     public OutputStream getOutputStream() {
  353.     return serverOutput;
  354.     }
  355.  
  356.     public void setAuthentication(String au) {
  357.     authentication = au;
  358.     }
  359.  
  360.     public void setAuthentication(AuthenticationInfo info) {
  361.     if (info == null) {
  362.         authentication = "";
  363.         } else {
  364.         authentication = info.auth;
  365.         }
  366.     }
  367.  
  368.     
  369.     public String getAuthentication() {
  370.     if (authentication  == null) {
  371.         return "";
  372.     } else {
  373.         String  auth = "Authorization: " + authentication + "\r\n";
  374.         return auth;
  375.     }
  376.     }
  377.  
  378.     public String getAuthentication(URL url) {
  379.     AuthenticationInfo info = AuthenticationInfo.getAuth(url);
  380.     setAuthentication(info);
  381.     return getAuthentication();
  382.     }
  383.  
  384.  
  385.  
  386.     public String getAuthenticationScheme() {
  387.     return getAuthenticationField(1);
  388.     }
  389.  
  390.     public String getAuthenticationRealm() {
  391.     return getAuthenticationField(3);
  392.     }
  393.  
  394.     public String getAuthenticationField(int which) {
  395.     String    field = getHeaderField("www-authenticate");
  396.     if (field == null) {
  397.         return null;
  398.     }
  399.     StringTokenizer t = new StringTokenizer(field, " =\"");
  400.     while (--which > 0) {
  401.         t.nextToken();
  402.     }
  403.     if (t.hasMoreTokens()) {
  404.         return t.nextToken();
  405.     }
  406.     return null;
  407.     }
  408.  
  409.     public HttpClient(URL url, String auth, String proxy, int  proxyPort) throws UnauthorizedHttpRequestException, IOException {
  410.     this.proxy = proxy;
  411.     this.proxyPort = proxyPort;
  412.     setAuthentication(auth);
  413.     this.url = url;
  414.     int port = url.getPort();
  415.     if (port == -1) {
  416.         port = httpPortNumber;
  417.     }
  418.     openServer(url.getHost(), port);
  419.     }
  420.  
  421.     public HttpClient(URL url, String proxy, int  proxyPort)
  422.     throws UnauthorizedHttpRequestException, IOException {
  423.     this.proxy = proxy;
  424.     this.proxyPort = proxyPort;
  425.     this.url = url;
  426.     int port = url.getPort();
  427.     if (port == -1) {
  428.         port = httpPortNumber;
  429.     }
  430.     openServer(url.getHost(), port);
  431.     }
  432.  
  433.     public HttpClient(URL url, String auth)
  434.     throws UnauthorizedHttpRequestException, IOException {
  435.     this(url, auth, null, -1);
  436.     }
  437.  
  438.     public HttpClient(URL url)
  439.     throws UnauthorizedHttpRequestException, IOException {
  440.     this(url, null, -1);
  441.     }
  442. }
  443.