/**
         * Return an appropriate TimeStampResponse.
         * <p>
         * If genTime is null a timeNotAvailable error response will be returned.
         *
         * @param request the request this response is for.
         * @param serialNumber serial number for the response token.
         * @param genTime generation time for the response token.
         * @param provider provider to use for signature calculation.
         * @return
         * @throws NoSuchAlgorithmException
         * @throws NoSuchProviderException
         * @throws TSPException
         * </p>
         */
        public TimeStampResponse Generate(
            TimeStampRequest request,
            BigInteger serialNumber,
            DateTimeObject genTime)
        {
            TimeStampResp resp;

            try
            {
                if (genTime == null)
                {
                    throw new TspValidationException("The time source is not available.",
                                                     PkiFailureInfo.TimeNotAvailable);
                }

                request.Validate(acceptedAlgorithms, acceptedPolicies, acceptedExtensions);

                this.status = PkiStatus.Granted;
                this.AddStatusString("Operation Okay");

                PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo();

                ContentInfo tstTokenContentInfo;
                try
                {
                    TimeStampToken token   = tokenGenerator.Generate(request, serialNumber, genTime.Value);
                    byte[]         encoded = token.ToCmsSignedData().GetEncoded();

                    tstTokenContentInfo = ContentInfo.GetInstance(Asn1Object.FromByteArray(encoded));
                }
                catch (IOException e)
                {
                    throw new TspException("Timestamp token received cannot be converted to ContentInfo", e);
                }

                resp = new TimeStampResp(pkiStatusInfo, tstTokenContentInfo);
            }
            catch (TspValidationException e)
            {
                status = PkiStatus.Rejection;

                this.SetFailInfoField(e.FailureCode);
                this.AddStatusString(e.Message);

                PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo();

                resp = new TimeStampResp(pkiStatusInfo, null);
            }

            try
            {
                return(new TimeStampResponse(resp));
            }
            catch (IOException e)
            {
                throw new TspException("created badly formatted response!", e);
            }
        }