text: ﻿/*
   * Copyright (C) Alibaba Cloud Computing
   * All rights reserved.
   * 
   */
  
  using System;
  using System.Collections.Generic;
  using System.IO;
  
  using Aliyun.OSS.Common.Communication;
  using Aliyun.OSS.Common.Handlers;
  using Aliyun.OSS.Common.Internal;
  using Aliyun.OSS.Util;
  using Aliyun.OSS.Transform;
  
  namespace Aliyun.OSS.Commands
  {
      internal class PutObjectCommand : OssCommand<PutObjectResult>
      {
          private readonly PutObjectRequest _putObjectRequest;
  
          protected override string Bucket
          {
              get { return _putObjectRequest.BucketName; }
          } 
          
          protected override string Key
          {
              get { return _putObjectRequest.Key; }
          } 
          
          protected override bool LeaveRequestOpen
          {
              get { return true; }
          }
  
          protected override bool LeaveResponseOpen
          {
              get { return _putObjectRequest.IsNeedResponseStream(); }
          }
  
          private PutObjectCommand(IServiceClient client, Uri endpoint, ExecutionContext context,
                                   IDeserializer<ServiceResponse, PutObjectResult> deserializer,
                                   PutObjectRequest putObjectRequest)
              : base(client, endpoint, context, deserializer, putObjectRequest.UseChunkedEncoding)
          {
              _putObjectRequest = putObjectRequest;
          }
  
          protected override HttpMethod Method
          {
              get { return HttpMethod.Put; }
          }
  
          protected override Stream Content
          {
              get { return _putObjectRequest.Content; }
          }
  
          protected override IDictionary<string, string> Headers
          {
              get
              {
                  var headers = base.Headers;
                  _putObjectRequest.Populate(headers);
                  return headers;
              }
          }
  
          protected override IDictionary<string, string> Parameters
          {
              get
              {
                  var parameters = base.Parameters;
                  if (_putObjectRequest.Process != null)
                  {
                      parameters[RequestParameters.OSS_PROCESS] = _putObjectRequest.Process;
                  }
                  return parameters;
              }
          }
  
          public static PutObjectCommand Create(IServiceClient client, Uri endpoint, 
                                                ExecutionContext context, 
                                                PutObjectRequest putObjectRequest)
          {
              OssUtils.CheckBucketName(putObjectRequest.BucketName);
              OssUtils.CheckObjectKey(putObjectRequest.Key);
  
              if (putObjectRequest.Content == null)
                  throw new ArgumentNullException("content");
  
              // handle upload callback error 203
              if (putObjectRequest.IsCallbackRequest())
              {
                  context.ResponseHandlers.Add(new CallbackResponseHandler());
              }
  
              var conf = OssUtils.GetClientConfiguration(client);
              var originalStream = putObjectRequest.Content;
  
              // setup progress
              var callback = putObjectRequest.StreamTransferProgress;
              if (callback != null)
              {
                  originalStream = OssUtils.SetupProgressListeners(originalStream, conf.ProgressUpdateInterval, client, callback);
                  putObjectRequest.Content = originalStream;
              }
  
              // wrap input stream in MD5Stream
              if (conf.EnalbeMD5Check) 
              {
                  var streamLength = originalStream.CanSeek ? originalStream.Length : -1;
                  var hashStream = new MD5Stream(originalStream, null, streamLength);
                  putObjectRequest.Content = hashStream;
                  context.ResponseHandlers.Add(new MD5DigestCheckHandler(hashStream));
              }
              else if (conf.EnableCrcCheck)
              {
                  var streamLength = originalStream.CanSeek ? originalStream.Length : -1;
                  var hashStream = new Crc64Stream(originalStream, null, streamLength);
                  putObjectRequest.Content = hashStream;
                  context.ResponseHandlers.Add(new Crc64CheckHandler(hashStream));
              }
              
              return new PutObjectCommand(client, endpoint, context,
                                          DeserializerFactory.GetFactory().CreatePutObjectReusltDeserializer(putObjectRequest),
                                          putObjectRequest);
          }
      }
  }
  