class ZTSImpl implements KeyStore, ZTSHandler {

    X509CertRecord getValidatedX509CertRecord(ResourceContext ctx, final String provider,
            final String instanceId, final String principalName, X509Certificate cert,
            final String caller, final String requestDomain, final String principalDomain,
            final String hostName) {

        // extract our instance certificate record to make sure it
        // hasn't been revoked already

        X509CertRecord x509CertRecord = instanceCertManager.getX509CertRecord(provider,
                instanceId, principalName);
        if (x509CertRecord == null) {

            // if the record is not present check to see if we're in recovery
            // mode where if the certificate was issued before the configured
            // time we're going to assume it is valid and we'll just create
            // an object based on the configured details

            if (cert.getNotBefore().getTime() < x509CertRefreshResetTime) {
                x509CertRecord = insertX509CertRecord(ctx, principalName, provider, instanceId,
                        cert.getSerialNumber().toString(), false, cert.getNotAfter(), hostName);
            }

            if (x509CertRecord == null) {
                throw forbiddenError("Unable to find certificate record", caller, requestDomain, principalDomain);
            }
        }

        if (!principalName.equals(x509CertRecord.getService())) {
            throw requestError("service name mismatch - csr: " + principalName +
                    " cert db: " + x509CertRecord.getService(), caller, requestDomain, principalDomain);
        }

        // now we need to make sure the serial number for the certificate
        // matches to what we had issued previously. If we have a mismatch
        // then we're going to revoke this instance as it has been possibly
        // compromised

        String serialNumber = cert.getSerialNumber().toString();
        if (x509CertRecord.getCurrentSerial().equals(serialNumber)) {

            // update the record to mark current as previous
            // and we'll update the current set with our existing
            // details

            x509CertRecord.setPrevIP(x509CertRecord.getCurrentIP());
            x509CertRecord.setPrevTime(x509CertRecord.getCurrentTime());
            x509CertRecord.setPrevSerial(x509CertRecord.getCurrentSerial());

        } else if (!x509CertRecord.getPrevSerial().equals(serialNumber)) {

            // check to see if we're in recovery/migration mode in which
            // case the instance refreshed multiple times in a short period
            // and hit both old and new systems thus the sequence is no longer
            // valid - in this case we're going to not revoke since when
            // refreshed again next time, if this is truly invalid, we'll
            // revoke it at that time

            if (cert.getNotBefore().getTime() > x509CertRefreshResetTime) {
                revokeCertificateRefresh(principalName, serialNumber, x509CertRecord);
                throw forbiddenError("Certificate revoked", caller, requestDomain, principalDomain);
            }
        }

        return x509CertRecord;
    }

    public  ZTSImpl();
    public  ZTSImpl(CloudStore implCloudStore, DataStore implDataStore);

}