一个基于http协议的访问网络的封装类

转一个基于http协议的访问网络的封装类,使用时只需调用

public static synchronized byte[] connect(String url, byte[] data,String method, String contentType, long lowRange, long highRange,  boolean disableProxy, boolean detached)

 这个函数就可以了.

 

------------------------------------------
/**
 * NetConnection.java
 *
 * This code is protected under the Apache 2.0 license as mentioned in
 * the accompanying license.txt file.  The license.txt file MUST be located
 * within the same folder as this NetConnection.java source file.
 *
 * The license file may also be viewed online by
 * visiting http://www.apache.org/licenses/
 */


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

 

/**
 * This class provides robust network connectivity and exception handling
 * over an unreliable MIDP HttpConnection.
 *
 * In addition the caller may perform a combination of any of the below
 * functions.
 *
 * - Proxy-server thwarting
 * - HTTP range requests
 * - Thread-separated connections
 *
 * @author Jason Fuerstenberg (http://www.jay-f.jp)
 * @version 2004/03/15
 */
public final class NetConnection implements Runnable {
 
 /*
  * This class is implemented as a singleton since only
  * a single active connection is allowed.
  */
 private static NetConnection singleton = new NetConnection();
 
 
 /*
  * The underlying HttpConnection which is managed by this class.
  */
 private static HttpConnection httpConn;
 
 
 /*
  * To support multi-threaded network connections a series of
  * pass-through members are used/shared across the class' threads.
  */
 
 
 /*
  * The requested URL.
  *
  * This member serves a second purpose which is to prevent a caller
  * from directly calling the run() method which is public to adhere to
  * the Runnable interface.
  */
 private static String url;
 
 
 // The HTTP method used to make the connection.
 private static String method;
 
 // The posted data if any.
 private static byte[] data;
  
 // The content type (if the method is POST)
 private static String contentType;
 
 // The lower bound of the requested range.
 private static long lowRange;
 
 // The higher bound of the requested range.
 private static long highRange;
 
 /*
  * The flag to indicate that the request should attempt to thwart
  * any proxy servers by appending a timestamp to the request.
  */
 private static boolean disableProxy;
 
 /*
  * The flag to indicate that the connection should occur in a separate
  * thread.
  */
 private static boolean detached;
 
 // The response's byte array.
 private static byte[] response;
 
  
 /*
  * In the event of an exception occuring in the run() method during
  * synchronous or asynchronous execution the exception needs to be
  * communicated up the main application thread's call stack.  This static
  * member will be a reference for any exception that may have occured
  * and will be thrown after run() returns.
  *
  */
 private static Exception exceptionPipe;

 /*
  * The private constructor to enforce the singleton pattern
  * which this class implements.
  */
 private NetConnection() {
  // singleton
 }

 /**
  * Connects to a target URL.
  *
  * @param url The target URL
  * @param data The data to post (if any)
  * @param method HttpConnection.GET or HttpConnection.POST
  * @param contentType The content-type of the posted data (if any)
  * @param lowRange The byte offset within the requested resource from
  *      which the response will begin.
  * @param highRange The last byte the response will return or 0
  *    if requesting the entire resource.
  * @param disableProxy Attempts to prevent a given server from
  *       offering a cached proxy version of the
  *       requested resource.
  * @param detached Causes the connection to occur in a thread separate
  *    from the calling thread.  This call will block until
  *    the connection has ended.
  * @return A byte array containing the response from the server.
  * @throws IOException If a network error occured.
  */
 public static synchronized byte[] connect(String url, byte[] data,
   String method, String contentType, long lowRange, long highRange,
   boolean disableProxy, boolean detached) throws Exception {
  

  /*
   * Set all the pass-through members here.
   */
  exceptionPipe = null;
  NetConnection.url = url;
  NetConnection.data = data;
  NetConnection.method = method;
  NetConnection.contentType = contentType;
  NetConnection.lowRange = lowRange;
  NetConnection.highRange = highRange;
  NetConnection.disableProxy = disableProxy;
  NetConnection.detached = detached;
  

  // Preemptively try to disconnect from a previous connection!
  NetConnection.severConnection();

  
  if (detached) {
   /*
    * The caller has specified that the connection should occur
    * in a separate, detached thread.
    */
   Thread t = new Thread(singleton);
   t.start();
   
   /*
    * Enforce a wait here to provide the illusion of synchronous
    * execution despite having the connection in another thread.
    */
   singleton.forceWait();

  } else {
   /*
    * Call run() directly without creating a thread to launch it.
    */
   singleton.run();
  }
  
  /*
   * Reset the URL to null to prevent direct
   * calling of the run() method.
   */
  NetConnection.url = null;
  
  if (exceptionPipe != null) {
   /*
    * During the course of the connection an exception occured
    * and was communicated here by the exceptionPipe member.
    * Throw it from this location.
    */
   throw exceptionPipe;
  } 
  
  // successful connection, return response!
  return response;
 }
 

 /**
  * Performs the actual connection logic.
  * The connection may occur in a separate thread from that of the caller.
  *
  * @throws IllegalStateException if called directly by any class
  *    other than this one.
  */
 public void run() {
  
  if (url == null) {
   /*
    * The URL is used as a means to ascertain whether or not the
    * caller of this method was the connect() method.  Since it is
    * null the caller is directly calling run() so throw an exception.
    */
   throw new IllegalStateException("Cannot invoke this method!");
  }

  
  DataOutputStream dos = null;
  DataInputStream dis = null;
  StringBuffer buffer = null;
  
  
  /*
   * IMPLEMENTATION NOTE:
   *
   * From this section on, a series of try/catch/finally statements
   * is used to ensure the proper flow of the connection under a
   * wide variety of circumstances.  This seemingly verbose logic
   * is important for the proper exception handling and object
   * reclamation required to make subsequent connections
   * possible in the future.
   *
   * In addition, the catching of exception is not too particular
   * regarding the type of exception being thrown for a few reasons...
   *
   * 1. The handling of each exception type is identical
   * 2. Implementations may vary in which exceptions they throw
   *
   * In the interest of stability it is highly recommended to
   * leave this as is, even if it goes against orthodox practices.
   */


  try {

   int permissions = 0;
   
   // Setup the permissions
   if (HttpConnection.GET.equals(method)) {
    permissions = Connector.READ;
   } else if (HttpConnection.POST.equals(method)) {
    permissions = Connector.READ_WRITE;
   }
   
   
   if (disableProxy) {
    /*
     * To thwart the a given server's proxy cache
     * the logic will attach a query parameter to the
     * end of the URL with a millisecond timestamp which
     * will hopefully force the server to see this request as one
     * which has never previously occured for this client
     * and therefore entitled to a fresh copy of the requested
     * resource.
     */
    boolean hasQueryParams = false;
    
    char[] ca = url.toCharArray();

    for (int loop = 0; loop < url.length(); loop++) {
     
     if (ca[loop] == '?') {
      hasQueryParams = true;
      break;
     }
    }
    
    StringBuffer noProxyUrl = new StringBuffer();
    noProxyUrl.append(url);

    if (hasQueryParams) {
     noProxyUrl.append("&");
    } else {
     noProxyUrl.append("?");
    }
    noProxyUrl.append("no-proxy=");
    noProxyUrl.append(System.currentTimeMillis()); // timestamp
    
    /*
     * Reset the URL to include the "no-proxy" query
     * parameter.
     */
    url = noProxyUrl.toString();
   }
   
   

   // Open the connection and set the request method.
   httpConn = (HttpConnection) Connector.open(url, permissions, true);
   httpConn.setRequestMethod(method);

   //if (HttpConnection.GET.equals(method)) {
   if (permissions == Connector.READ) {
    // GET request
    
    if (lowRange > -1 && lowRange < highRange) {
     /*
      * The caller is requesting a specific range within
      * the resource.
      *
      * The logic will insert the appropriate HTTP header to
      * implement the request.
      */
     StringBuffer range = new StringBuffer();
     
     range.append("bytes=");
     range.append(lowRange);
     range.append("-");
     range.append(highRange);
     
     httpConn.setRequestProperty("Range", range.toString());
    }
   } else if (permissions == Connector.READ_WRITE) {
    // POST request
    httpConn.setRequestProperty("Content-Type", contentType);
    dos = httpConn.openDataOutputStream();
    dos.write(data);
   }
   
  } catch (Exception e) {
   /*
    * An exception occured either during the opening of the connection
    * or during the POSTing of data.  In either case the logic cannot
    * continue and will quit here.
    */
   exceptionPipe = e;

   if (detached) {
    forceNotify();
   }
   
   return;
   
  } finally {

   try {
    try {
     if (dos != null) {
      // Close the DataOutputStream.
      dos.close();
     }
    } catch (Exception e) {
     // Failure to close the DataOutputStream!
     if (exceptionPipe == null) {
      exceptionPipe = e;
      
      if (detached) {
       forceNotify();
      }
      return;
     }
    } finally {
     // Force the dereferencing of the DataOutputStream.
     dos = null;
    }
    
    // Get the response code.
    int responseCode = httpConn.getResponseCode();
    
    if (responseCode != HttpConnection.HTTP_OK
      && responseCode != HttpConnection.HTTP_PARTIAL) {

     /*
      * The response code does not match HTTP_OK (200)
      * or HTTP_PARTIAL (206).  The logic cannot proceed to
      * treat the response as one holding the requested
      * resource and therefore will report the response code
      * via an exception to the caller.
      */
     if (exceptionPipe == null) {
      StringBuffer errorCode = new StringBuffer();
      errorCode.append("Response code from server: ");
      errorCode.append(responseCode);
      errorCode.append("/nMessage: [");
      errorCode.append(httpConn.getResponseMessage());
      errorCode.append("]");
      
      exceptionPipe = new IOException(errorCode.toString());
      
      if (detached) {
       forceNotify();
      }
      return;
     }
    }

    dis = httpConn.openDataInputStream();

    /*
     * Cycle through all the bytes provided
     * in the response and append them to a
     * StringBuffer for later use.
     */
    int ch;
    buffer = new StringBuffer();
          while ((ch = dis.read()) != -1) {
           buffer.append((char) ch);
          }

          /*
           * Convert the StringBuffer to an array using
           * the ISO-8859-1 encoding to preserve the byte
           * encoding of the characters.
           */
    response = buffer.toString().getBytes("ISO8859_1");
    
    if (detached) {
     forceNotify();
    }
    
    /*
     * All OK, now returning.
     */
    return;

   } catch (Exception e) {
    /*
     * An exception occured either during the usage of the
     * connection object (such as a NullPointerException) or during
     * the reading of the data.  In either case the logic cannot
     * continue.
     */
    if (exceptionPipe == null) {
     exceptionPipe = e;
     
     if (detached) {
      forceNotify();
     }
     
     return;
    }
   } finally {
      
    try {
     if (dis != null) {
      // Close the DataInputStream.
      dis.close();
     }
    } catch (Exception e) {
     // Failure to close the DataInputStream!
     if (exceptionPipe == null) {
      exceptionPipe = e;
      
      if (detached) {
       forceNotify();
      }
      return;
     }
    } finally {
     // force the dereferencing of the DataInputStream.
     dis = null;
    }
    
    try {
     if (httpConn != null) {
      // Close the HttpConnection.
      httpConn.close();
      
      /*
       * Only dereference the HttpConnection if the
       * closing actually succeeded!
       */
      httpConn = null;
     }
    } catch (Exception e) {
     // Failure in closing the HttpConnection!
     if (exceptionPipe == null) {
      exceptionPipe = e;
      
      if (detached) {
       forceNotify();
      }
      return;
     }
    }
   }
  }
 }
 
 /*
  * Provides the synchronized context against the singleton's instance
  * for the wait() method call to properly execute.  Not all implementations
  * of the JVM support the concept of synchronized contexts other than
  * that of an entire method.  As such the inner call to wait must be
  * embedded in this synchronized method.
  */
 private synchronized void forceWait() {
  
  try {
   wait();
  } catch (InterruptedException ie) {
   // Ignore this exception
   ie = null;
  }
 }
 
 
 /*
  * Provides the synchronized context against the singleton's instance
  * for the notify() method call to properly execute.  Not all
  * implementations of the JVM support the concept of synchronized
  * contexts other than that of an entire method.  As such the inner
  * call to notify must be embedded in this synchronized method.
  */
 private synchronized void forceNotify() {
  notify();
 }
 
 /*
  * Severs an ongoing connection.
  */
 private static void severConnection() {
  
     try {
   if (httpConn == null) {
    /*
     * No connection is in progress so simply return
     * to the caller.
     */
    return;
   }
   
   // Close the connection.
      httpConn.close();

  } catch (Exception e) {
   /*
    * If the handset's implementation of the HttpConnection
    * interface is solid it will not be possible for
    * an exception to occur.
    */
   e = null;
  } finally {
   // Force the dereferencing of the connection.
   httpConn = null;
  }
 }
}

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页