/// <summary>
 /// Creates a transfer object for a given requested resource.
 /// </summary>
 /// <param name="submittedResourceFilePath">The resource identifier as submitted.</param>
 /// <param name="fileItem">Represents the requested file resource.</param>
 /// <param name="token">The token that is being issued for the transfer.</param>
 /// <param name="claims">The access rights for the resource.</param>
 /// <param name="lockGuard">File locks, if necessary. Can be a null reference
 /// if no locking takes place.</param>
 /// <param name="expirationJob">A scheduled job that invokes the
 /// <see cref="TransferHandlerBase{TFile,TToken,TTransfer}.OnTransferExpiration"/>
 /// method once the transfer expires. May be null if the token does not expire.</param>
 /// <returns>A transfer object which encapsulates the information required to perform
 /// the transfer.</returns>
 protected abstract TTransfer CreateTransfer(string submittedResourceFilePath, TFile fileItem, DownloadToken token,
                                             FileClaims claims, ResourceLockGuard lockGuard,
                                             Job <DownloadToken> expirationJob);
        private TTransfer InitTransferImpl(string submittedResourceFilePath, int?clientMaxBlockSize, bool includeFileHash)
        {
            const FileSystemTask context = FileSystemTask.DownloadTokenRequest;
            TFile fileItem = CreateFileItemImpl(submittedResourceFilePath, false, context);

            if (!fileItem.Exists)
            {
                Auditor.AuditRequestedFileNotFound(fileItem, context);

                string msg = String.Format("Resource [{0}] not found.", submittedResourceFilePath);
                throw new VirtualResourceNotFoundException(msg)
                      {
                          IsAudited = true
                      };
            }

            //get authorization
            FileClaims claims = GetFileClaims(fileItem);

            if (!claims.AllowReadData)
            {
                Auditor.AuditDeniedOperation(context, AuditEvent.FileDataDownloadDenied, fileItem);

                string msg = "Read request for file [{0}] was denied - you are not authorized to read the resource.";
                msg = String.Format(msg, submittedResourceFilePath);
                throw new ResourceAccessException(msg)
                      {
                          IsAudited = true
                      };
            }

            //try to get lock
            ResourceLockGuard readLock = LockResourceForDownload(fileItem, claims);

            if (readLock != null && !readLock.IsLockEnabled)
            {
                Auditor.AuditDeniedOperation(context, AuditEvent.FileReadLockDenied, fileItem);

                string msg = "The requested file [{0}] is currently locked and thus cannot be accessed.";
                msg = String.Format(msg, submittedResourceFilePath);
                throw new ResourceLockedException(msg)
                      {
                          IsAudited = true
                      };
            }

            //create download token
            DownloadToken token = CreateDownloadToken(submittedResourceFilePath, fileItem, clientMaxBlockSize, includeFileHash);

            //create expiration job if we have an expiration time
            Job <DownloadToken> job = null;

            if (token.ExpirationTime.HasValue)
            {
                job = ScheduleExpiration(token);
            }

            //create transfer instance
            TTransfer transfer = CreateTransfer(submittedResourceFilePath, fileItem, token, claims, readLock, job);

            //cache transfer
            TransferStore.AddTransfer(transfer);

            //audit issued token
            Auditor.AuditResourceOperation(context, AuditEvent.DownloadTokenIssued, fileItem);

            return(transfer);
        }