📄 httpconnectionhelper.java
字号:
//
// $Id: FileUploadThreadHTTP.java 488 2008-07-06 20:21:43Z etienne_sf $
//
// jupload - A file upload applet.
// Copyright 2007 The JUpload Team
//
// Created: 2007-03-07
// Creator: etienne_sf
// Last modified: $Date: 2008-07-06 22:21:43 +0200 (dim., 06 juil. 2008) $
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version. This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details. You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation, Inc.,
// 675 Mass Ave, Cambridge, MA 02139, USA.
package wjhk.jupload2.upload.helper;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import wjhk.jupload2.exception.JUploadException;
import wjhk.jupload2.exception.JUploadIOException;
import wjhk.jupload2.policies.UploadPolicy;
/**
*
* This class contains utilities to delegate network manipulation. It hides the
* management for the current upload policy connection parameters.<BR>
* This class goes through the following states, stored in the private
* connectionStatus attribute: <DIR> <LI>STATUS_NOT_INITIALIZED: default status
* when the instance in created. Only available action:
* {@link #initRequest(URL, String, boolean, boolean)} <LI>
* STATUS_BEFORE_SERVER_CONNECTION: the instance is initialized, and the caller
* may begin writing the request to this ConnectionHelper. All data written to
* it, will be stored in a {@link ByteArrayEncoderHTTP}. The connection switches
* to this status when the {@link #initRequest(URL, String, boolean, boolean)}
* is called. <LI>STATUS_WRITING_REQUEST: The network connection to the server
* is now opened. The content of the ByteArrayEncoderHTTP has been sent to the
* server. All subsequent calls to write methods will directly write on the
* socket to the server. The {@link #sendRequest()} method changes the
* connection to this status. <LI>STATUS_READING_RESPONSE: The request to the
* server has been totally written. No more calls to the write methods are
* allowed. The {@link #readHttpResponse()} is responsible to put the
* connectionHelper to this status. <LI>STATUS_CONNECTION_CLOSED: The response
* has been read. All getters can be called, to get information about the server
* response. The only other method allowed is the
* {@link #initRequest(URL, String, boolean, boolean)}, to start a new request
* to the server. Using the same connectionHelper allows to use the same network
* connection, when the allowHttpPersistent applet parameter is used. </DIR>
*
* @author etienne_sf
*
*/
public class HTTPConnectionHelper extends OutputStream {
// ////////////////////////////////////////////////////////////////////////////////////
// /////////////////// PRIVATE CONSTANTS
// ////////////////////////////////////////////////////////////////////////////////////
/**
* Indicates that the connection has not been initialized. The only
* authorized action in this state is a call to
* {@link #initRequest(URL, String, boolean, boolean)}.
*/
final static private int STATUS_NOT_INITIALIZED = 0;
/**
* Indicates that the network connection to the server has not been opened.
* All data sent to the ConnectionHelper with write methods are sent to the
* current ByteArrayEncoder.
*/
final static private int STATUS_BEFORE_SERVER_CONNECTION = 1;
/**
* Indicates that the network connection to the server is opened, but the
* request has not been totally sent to the server. All data sent to the
* ConnectionHelper with write methods is sent to the network connection,
* that is: to the current OutputStream. <BR>
* That is: the ByteArrayEncoder is now read only (closed).
*/
final static private int STATUS_WRITING_REQUEST = 2;
/**
* Indicates that the network connection to the server is opened, but the
* request has not been totally sent to the server. All data sent to the
* ConnectionHelper with write methods is sent to the network connection,
* that is: to the current OutputStream. <BR>
* That is: the ByteArrayEncoder is now read only (closed).
*/
final static private int STATUS_READING_RESPONSE = 3;
/**
* Indicates that the network connection to the server is now closed, that
* is: we've written the request, read the response, and free the server
* connection. If the keepAlive parameter is used, the connection may remain
* opened for the next request. <BR>
* No more action may be done on this connection helper, out of reading
* data, until the application do a call to
* {@link #initRequest(URL, String, boolean, boolean)}.
*/
final static private int STATUS_CONNECTION_CLOSED = 4;
// ////////////////////////////////////////////////////////////////////////////////////
// /////////////////// ATTRIBUTE USED TO CONTROL THE OUTPUT TO THE SERVER
// ////////////////////////////////////////////////////////////////////////////////////
/**
* http boundary, for the posting multipart post.
*/
private String boundary = calculateRandomBoundary();
/**
* Is chunk upload on for this request ?
*/
private boolean bChunkEnabled;
/**
* Is it the last chunk ? If yes, we'll try to keep the connection open,
* according to the current applet configuration.
*/
private boolean bLastChunk;
/**
* The encoder that will contain the HTTP request.
*/
private ByteArrayEncoder byteArrayEncoder = null;
/**
* Indicates where data sent to appendXxx method should be added. It must be
* one of the SENDING_XXX private strings.
*/
private int connectionStatus = STATUS_NOT_INITIALIZED;
/**
* Contains the HTTP reader. All data coming from the server response are
* read from it. If this attribute is null, it means that the server
* response has not been read.
*/
private HTTPInputStreamReader httpInputStreamReader = null;
/**
* This stream allows the applet to get the server response. It is opened
* and closed as the {@link #outputStream}.
*/
private PushbackInputStream inputStream = null;
/**
* The HTTP method: POST, GET, HEAD...
*/
private String method = null;
/**
* This stream is open by {@link #sendRequest()}. It is closed by the
* {@link #readHttpResponse()} method.
*
* @see #sendRequest()
* @see #readHttpResponse()
* @see #getOutputStream()
*/
private DataOutputStream outputStream = null;
/**
* The current proxy, if any
*/
private Proxy proxy = null;
/**
* The network socket where the bytes should be written.
*/
private Socket socket = null;
/**
* Indicates if the user request to stop the upload.
*/
private boolean stop = false;
/**
* The current upload policy
*/
private UploadPolicy uploadPolicy = null;
/**
* The current URL
*/
private URL url = null;
/**
* Should we use a proxy
*/
private boolean useProxy;
/**
* Is SSL mode on ?
*/
private boolean useSSL;
// ////////////////////////////////////////////////////////////////////////////////////
// /////////////////////// PUBLIC METHODS
// ////////////////////////////////////////////////////////////////////////////////////
/**
* The standard constructor for this class.
*
* @param uploadPolicy The current upload policy.
*/
public HTTPConnectionHelper(UploadPolicy uploadPolicy) {
this.uploadPolicy = uploadPolicy;
}
/**
* The standard constructor for this class.
*
* @param url The target URL
* @param method The HTTP method (POST, GET, HEAD...)
* @param bChunkEnabled Indicates if chunkUpload is enabled for this query.
* Put false, if non chunked request or if it is not relevant.
* @param bLastChunk Indicates whether this chunk is the last one. Put true,
* if non chunked request or if it is not relevant.
* @param uploadPolicy The current upload policy.
* @throws JUploadIOException
*/
public HTTPConnectionHelper(URL url, String method, boolean bChunkEnabled,
boolean bLastChunk, UploadPolicy uploadPolicy)
throws JUploadIOException {
this.uploadPolicy = uploadPolicy;
initRequest(url, method, bChunkEnabled, bLastChunk);
}
/**
* The standard constructor for this class.
*
* @param url The target URL
* @param bChunkEnabled Indicates if chunkUpload is enabled for this query.
* Put false, if non chunked request or if it is not relevant.
* @param method The HTTP method (POST, GET, HEAD...)
* @param bLastChunk Indicates whether this chunk is the last one. Put true,
* if non chunked request or if it is not relevant.
* @throws JUploadIOException
*/
public void initRequest(URL url, String method, boolean bChunkEnabled,
boolean bLastChunk) throws JUploadIOException {
// This method expects that the connection has not been initialized yet,
// or that the previous request is finished.
if (this.connectionStatus != STATUS_NOT_INITIALIZED
&& this.connectionStatus != STATUS_CONNECTION_CLOSED) {
throw new JUploadIOException(
"Bad status of the connectionHelper in initRequest: "
+ getStatusLabel());
}
// Clean any current request.
if (isKeepAlive()) {
dispose();
}
// Load the new parameters.
this.url = url;
this.method = method;
this.bChunkEnabled = bChunkEnabled;
this.bLastChunk = bLastChunk;
// We will write to the local ByteArrayEncoder, until a connection to
// the server is opened.
initByteArrayEncoder();
// Ok, the connectionHelper is now ready to get write commands.
this.connectionStatus = STATUS_BEFORE_SERVER_CONNECTION;
}
/**
* Return the current {@link ByteArrayEncoder}. If it was not created, it is
* initialized.
*
* @return The current {@link ByteArrayEncoder}, null if called before the
* first initialization.
* @throws JUploadIOException
* @see #initRequest(URL, String, boolean, boolean)
*/
public ByteArrayEncoder getByteArrayEncoder() throws JUploadIOException {
return this.byteArrayEncoder;
}
/**
* @return Returns the boundary for this HTTP request.
*
*/
public String getBoundary() {
return this.boundary;
}
/**
* Closes the byteArrayEncoder, create the socket (or not, depending on the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -