content: package com.bedpotato.musicplayerproxy.utils;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.Socket;
  import java.net.SocketException;
  
  import org.apache.http.Header;
  import org.apache.http.HttpResponse;
  import org.apache.http.client.methods.HttpUriRequest;
  
  import android.util.Log;
  
  import com.bedpotato.musicplayerproxy.Constants;
  import com.bedpotato.musicplayerproxy.db.CacheFileInfoDao;
  
  public class RequestDealThread extends Thread {
  	private static final String LOG_TAG = RequestDealThread.class.getSimpleName();
  
  	Socket client;
  	HttpUriRequest request;
  
  	ProxyFileUtils fileUtils;
  	/** MediaPlayer发出的原始请求Range Start */
  	private int originRangeStart;
  	/** 和本地缓存判断后，需要发出的请求Range Start */
  	private long realRangeStart;
  
  	CacheFileInfoDao cacheDao;
  
  	public RequestDealThread(HttpUriRequest request, Socket client) {
  		this.request = request;
  		this.client = client;
  		cacheDao = CacheFileInfoDao.getInstance();
  	}
  
  	@Override
  	public void run() {
  		try {
  			fileUtils = ProxyFileUtils.getInstance(request.getURI(), true);
  			processRequest(request, client);
  		} catch (IllegalStateException e) {
  			e.printStackTrace();
  		} catch (IOException e) {
  			e.printStackTrace();
  		}
  	}
  
  	private int getRangeStart(HttpUriRequest request) {
  		Header rangeHeader = request.getFirstHeader(Constants.RANGE);
  		if (rangeHeader != null) {
  			String value = rangeHeader.getValue();
  			return Integer.valueOf(value.substring(value.indexOf("bytes=") + 6, value.indexOf("-")));
  		}
  		return 0;
  	}
  
  	/**
  	 * 伪造Response Header，发送缓存内容
  	 * 
  	 * @param rangeStart
  	 *            数据起始位置（如果从头开始则为0）
  	 * @param rangeEnd
  	 *            数据截止位置（一般为缓存长度-1）
  	 * @param fileLength
  	 *            缓存文件长度
  	 * @param audioCache
  	 *            缓存内容
  	 * @throws IOException
  	 */
  	private void sendLocalHeaderAndCache(int rangeStart, int rangeEnd, int fileLength, byte[] audioCache)
  			throws IOException {
  		// 返回MediaPlayer Header信息
  		String httpString = HttpUtils.genResponseHeader(rangeStart, rangeEnd, fileLength);
  		byte[] httpHeader = httpString.toString().getBytes();
  		client.getOutputStream().write(httpHeader, 0, httpHeader.length);
  		// 返回Content
  		if (audioCache != null && audioCache.length > 0) {
  			client.getOutputStream().write(audioCache, 0, audioCache.length);
  		}
  	}
  
  	private void processRequest(HttpUriRequest request, Socket client) throws IllegalStateException, IOException {
  		if (request == null) {
  			return;
  		}
  
  		try {
  			byte[] audioCache = null;
  			// 得到MediaPlayer原始请求Range起始
  			originRangeStart = getRangeStart(request);
  			Log.i(LOG_TAG, "原始请求Range起始值：" + originRangeStart + " 本地缓存长度：" + fileUtils.getLength());
  			// 缓存的文件大小
  			int cacheFileSize = cacheDao.getFileSize(fileUtils.getFileName());
  			/*
  			 * 如果缓存完成，无需发送请求，本地缓存返回MediaPlayer。
  			 */
  			if (fileUtils.isEnable() && fileUtils.getLength() == cacheFileSize) {
  				audioCache = fileUtils.read(originRangeStart, Constants.AUDIO_BUFFER_MAX_LENGTH);
  				sendLocalHeaderAndCache(originRangeStart, cacheFileSize - 1, cacheFileSize, audioCache);
  				return;
  			}
  			// TODO 这里可能需要网络判断
  			/*
  			 * 请求Range起始值和本地缓存比对。如果有缓存，得到缓存内容，修改Range。 如果没有缓存，则Range不变。
  			 */
  			if (fileUtils.isEnable() && originRangeStart < fileUtils.getLength()) {
  				audioCache = fileUtils.read(originRangeStart, Constants.AUDIO_BUFFER_MAX_LENGTH);
  				Log.i(LOG_TAG, "本地已缓存长度（跳过）:" + audioCache.length);
  				// 得到需要发送请求Range Start（本地缓存结尾位置+1=缓存长度）
  				realRangeStart = fileUtils.getLength();
  				// 替换请求Header
  				request.removeHeaders(Constants.RANGE);
  				request.addHeader(Constants.RANGE, Constants.RANGE_PARAMS + realRangeStart + "-");
  			} else {
  				realRangeStart = originRangeStart;
  			}
  			// 缓存是否已经到最大值（如果缓存已经到最大值，则只需要返回缓存）
  			boolean isCacheEnough = (audioCache != null && audioCache.length == Constants.AUDIO_BUFFER_MAX_LENGTH) ? true
  					: false;
  
  			/*
  			 * 如果缓存足够，且本地有文件长度，则直接发送缓存,不发送请求。。。。。。。。。。。。。。。。。。。
  			 * 如果缓存足够，本地没有文件长度，则发送请求，使用ResponseHeader，返回缓存,!不接收ResponseContent
  			 * 如果缓存不足，则发送请求，使用ResponseHeader，返回缓存，!返回Response Content
  			 */
  			// 缓存足够&&有文件大小
  			if (isCacheEnough && cacheFileSize > 0) {
  				sendLocalHeaderAndCache(originRangeStart, cacheFileSize - 1, cacheFileSize, audioCache);
  			}
  			// 缓存不够。或者数据库没有文件大小
  			else {
  				HttpResponse realResponse = null;
  				/*
  				 * 返回Header和Cache
  				 */
  				// 如果数据库没有存文件大小，则获取（处理数据库没有文件大小的情况）
  				if (cacheFileSize <= 0) {
  					Log.d(LOG_TAG, "数据库未包含文件大小，发送请求");
  					realResponse = HttpUtils.send(request);
  					if (realResponse == null) {
  						return;
  					}
  					cacheFileSize = getContentLength(realResponse);
  				}
  				sendLocalHeaderAndCache(originRangeStart, cacheFileSize - 1, cacheFileSize, audioCache);
  				// 如果缓存不足，返回Response Content（处理缓存不足的情况）
  				if (realResponse == null) {
  					Log.d(LOG_TAG, "缓存不足，发送请求");
  					realResponse = HttpUtils.send(request);
  					if (realResponse == null) {
  						return;
  					}
  				}
  				Log.d(LOG_TAG, "接收ResponseContent");
  				InputStream data = realResponse.getEntity().getContent();
  				if (!isCacheEnough) {
  					byte[] buff = new byte[1024 * 40];
  					boolean isPrint = true;
  					int fileLength = 0;
  					int readBytes;
  					while (Thread.currentThread() == MediaPlayerProxy.downloadThread
  							&& (readBytes = data.read(buff, 0, buff.length)) != -1) {
  						long fileBufferLocation = fileLength + realRangeStart;
  						fileLength += readBytes;
  						long fileBufferEndLocation = fileLength + realRangeStart;
  						// 保存文件
  						if (fileUtils.getLength() == fileBufferLocation) {
  							fileUtils.write(buff, readBytes);
  						}
  						// 打印缓存大小
  						if (System.currentTimeMillis() / 1000 % 2 == 0) {
  							if (isPrint) {
  								Log.d(LOG_TAG, "Cache Size:" + readBytes + " File Start:" + fileBufferLocation
  										+ "File End:" + fileBufferEndLocation);
  								isPrint = false;
  							}
  						} else {
  							isPrint = true;
  						}
  						client.getOutputStream().write(buff, 0, readBytes);
  					}
  				}
  			}
  		} catch (SocketException e) {
  			Log.i(LOG_TAG, "连接被终止", e);
  		} catch (Exception e) {
  			Log.e(LOG_TAG, e.getMessage(), e);
  		} finally {
  			client.close();
  			Log.i(LOG_TAG, "代理关闭");
  		}
  	}
  
  	/**
  	 * 得到Content大小
  	 * 
  	 * @param response
  	 * @return
  	 */
  	private int getContentLength(HttpResponse response) {
  		int contentLength = 0;
  		Header header = response.getFirstHeader(Constants.CONTENT_RANGE);
  		if (header != null) {
  			String range = header.getValue();
  			contentLength = Integer.valueOf(range.substring(range.indexOf("-") + 1, range.indexOf("/"))) + 1;
  		} else {
  			header = response.getFirstHeader(Constants.CONTENT_LENGTH);
  			if (header != null) {
  				contentLength = Integer.valueOf(header.getValue());
  			}
  		}
  		if (contentLength != 0) {
  			cacheDao.insertOrUpdate(fileUtils.getFileName(), contentLength);
  		}
  		return contentLength;
  	}
  }
  