content: /*
   * Created by LuaView.
   * Copyright (c) 2017, Alibaba Group. All rights reserved.
   *
   * This source code is licensed under the MIT.
   * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
   */
  
  package com.taobao.luaview.scriptbundle.asynctask.delegate;
  
  import com.taobao.luaview.scriptbundle.LuaScriptManager;
  import com.taobao.luaview.util.DebugUtil;
  import com.taobao.luaview.util.EncryptUtil;
  import com.taobao.luaview.util.FileUtil;
  import com.taobao.luaview.util.HexUtil;
  import com.taobao.luaview.util.IOUtil;
  import com.taobao.luaview.util.LogUtil;
  
  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.RandomAccessFile;
  import java.net.HttpURLConnection;
  import java.net.URL;
  
  /**
   * ScriptBundle Download Delegate
   *
   * @author song
   * @date 17/2/8
   * 主要功能描述
   * 修改描述
   * 下午2:42 song XXX
   */
  
  public class ScriptBundleDownloadDelegate {
      private String url;
      private String sha256;
  
      public ScriptBundleDownloadDelegate(String url, String sha256) {
          this.url = url;
          this.sha256 = sha256;
      }
  
      /**
       * download ScriptBundle
       *
       * @return
       */
      public boolean download() {
          byte[] fileData = downloadAsBytes();
  
          if (fileData != null) {//save file
              DebugUtil.tsi("luaviewp-saveFiles0");
  
              saveFile(fileData);
  
              DebugUtil.tei("luaviewp-saveFiles0");
  
              return true;
          }
  
          return false;
      }
  
      public void saveFile(byte[] fileData){
          String destFilePath = LuaScriptManager.buildScriptBundleFilePath(url);
          File destFile = FileUtil.createFile(destFilePath);
          saveFileUsingFileOutputStream(destFile, fileData);
      }
  
      /**
       * download as bytes
       *
       * @return
       */
      public byte[] downloadAsBytes() {
          HttpURLConnection connection = createHttpUrlConnection();
          if (connection != null) {
              InputStream input = downloadAsStream(connection);
              if (input != null) {
                  DebugUtil.tsi("luaviewp-readBytes");
                  final byte[] fileData = IOUtil.toBytes(input);//TODO 有性能瓶颈，可以考虑安全验证
                  DebugUtil.tei("luaviewp-readBytes");
  
                  DebugUtil.tsi("luaviewp-sha256");
                  if (!checkSha256(fileData)) {
                      return null;
                  }
                  DebugUtil.tei("luaviewp-sha256");
  
                  try {
                      input.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
  
                  connection.disconnect();
  
                  return fileData;
              }
          }
          return null;
      }
  
      /**
       * create HttpURLConnection
       *
       * @return
       */
      public HttpURLConnection createHttpUrlConnection() {
          try {
  
              final URL uri = new URL(url);
              HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
              connection.connect();
  
              return connection;
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * download as Stream
       *
       * @param connection
       * @return
       */
      public InputStream downloadAsStream(HttpURLConnection connection) {
          try {
              if (connection != null) {
                  if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                      LogUtil.e("[Server Returned HTTP] ", connection.getResponseCode(), connection.getResponseMessage());
                      return null;
                  }
                  return new BufferedInputStream(connection.getInputStream());
              }
              return null;
          } catch (Exception e) {
              LogUtil.e("[Script Download Error] ", e);
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * check sha256
       *
       * @param fileData
       * @return
       */
      public boolean checkSha256(byte[] fileData) {
          if (sha256 != null && !sha256.equalsIgnoreCase(HexUtil.bytesToHex(EncryptUtil.sha256(fileData)))) {//验证脚本的完整性
              return false;
          }
          return true;
      }
  
      /**
       * save file using output stream
       *
       * @param destFile
       * @param fileData
       */
      private void saveFileUsingFileOutputStream(File destFile, byte[] fileData) {
          FileOutputStream output = null;
          try {
              output = new FileOutputStream(destFile);
              output.write(fileData);
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              if (output != null) {
                  try {
                      output.flush();
                      output.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
  
      /**
       * save file
       *
       * @param destFile
       * @param fileData
       */
      private void saveFileUsingRandomAccessFile(File destFile, byte[] fileData) {
          try {
              RandomAccessFile randomAccessFile = new RandomAccessFile(destFile, "rw");
              randomAccessFile.write(fileData);
              randomAccessFile.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  }
  