OpenSslKeyMaterial chooseKeyMaterial(ByteBufAllocator allocator, String alias) throws Exception {
        X509Certificate[] certificates = keyManager.getCertificateChain(alias);
        if (certificates == null || certificates.length == 0) {
            return null;
        }

        PrivateKey key = keyManager.getPrivateKey(alias);
        PemEncoded encoded = PemX509Certificate.toPEM(allocator, true, certificates);
        long chainBio = 0;
        long pkeyBio = 0;
        long chain = 0;
        long pkey = 0;
        try {
            chainBio = toBIO(allocator, encoded.retain());
            chain = SSL.parseX509Chain(chainBio);

            OpenSslKeyMaterial keyMaterial;
            if (key instanceof OpenSslPrivateKey) {
                keyMaterial = ((OpenSslPrivateKey) key).newKeyMaterial(chain, certificates);
            } else {
                pkeyBio = toBIO(allocator, key);
                pkey = key == null ? 0 : SSL.parsePrivateKey(pkeyBio, password);
                keyMaterial = new DefaultOpenSslKeyMaterial(chain, pkey, certificates);
            }

            // See the chain and pkey to 0 so we will not release it as the ownership was
            // transferred to OpenSslKeyMaterial.
            chain = 0;
            pkey = 0;
            return keyMaterial;
        } finally {
            SSL.freeBIO(chainBio);
            SSL.freeBIO(pkeyBio);
            if (chain != 0) {
                SSL.freeX509Chain(chain);
            }
            if (pkey != 0) {
                SSL.freePrivateKey(pkey);
            }
            encoded.release();
        }
    }
@Test
    public void testChooseOpenSslPrivateKeyMaterial() throws Exception {
        PrivateKey privateKey = SslContext.toPrivateKey(
                getClass().getResourceAsStream("localhost_server.key"),
                null);
        assertNotNull(privateKey);
        assertEquals("PKCS#8", privateKey.getFormat());
        final X509Certificate[] certChain = SslContext.toX509Certificates(
                getClass().getResourceAsStream("localhost_server.pem"));
        assertNotNull(certChain);
        PemEncoded pemKey = null;
        long pkeyBio = 0L;
        OpenSslPrivateKey sslPrivateKey;
        try {
            pemKey = PemPrivateKey.toPEM(ByteBufAllocator.DEFAULT, true, privateKey);
            pkeyBio = ReferenceCountedOpenSslContext.toBIO(ByteBufAllocator.DEFAULT, pemKey.retain());
            sslPrivateKey = new OpenSslPrivateKey(SSL.parsePrivateKey(pkeyBio, null));
        } finally {
            ReferenceCountUtil.safeRelease(pemKey);
            if (pkeyBio != 0L) {
                SSL.freeBIO(pkeyBio);
            }
        }
        final String keyAlias = "key";

        OpenSslKeyMaterialProvider provider = new OpenSslKeyMaterialProvider(
                new SingleKeyManager(keyAlias, sslPrivateKey, certChain),
                null);
        OpenSslKeyMaterial material = provider.chooseKeyMaterial(ByteBufAllocator.DEFAULT, keyAlias);
        assertNotNull(material);
        assertEquals(2, sslPrivateKey.refCnt());
        assertEquals(1, material.refCnt());
        assertTrue(material.release());
        assertEquals(1, sslPrivateKey.refCnt());
        // Can get material multiple times from the same key
        material = provider.chooseKeyMaterial(ByteBufAllocator.DEFAULT, keyAlias);
        assertNotNull(material);
        assertEquals(2, sslPrivateKey.refCnt());
        assertTrue(material.release());
        assertTrue(sslPrivateKey.release());
        assertEquals(0, sslPrivateKey.refCnt());
        assertEquals(0, material.refCnt());
        assertEquals(0, ((OpenSslPrivateKey.OpenSslPrivateKeyMaterial) material).certificateChain);
    }