DefaultConnection implements Connection { @Override public List<X509Certificate> readCertificates() throws AcmeException { assertConnectionIsOpen(); String contentType = AcmeUtils.getContentType(conn.getHeaderField(CONTENT_TYPE_HEADER)); if (!(MIME_CERTIFICATE_CHAIN.equals(contentType))) { throw new AcmeProtocolException("Unexpected content type: " + contentType); } try (InputStream in = new TrimmingInputStream(conn.getInputStream())) { CertificateFactory cf = CertificateFactory.getInstance("X.509"); return cf.generateCertificates(in).stream() .map(c -> (X509Certificate) c) .collect(toList()); } catch (IOException ex) { throw new AcmeNetworkException(ex); } catch (CertificateException ex) { throw new AcmeProtocolException("Failed to read certificate", ex); } } DefaultConnection(HttpConnector httpConnector); @Override void resetNonce(Session session); @Override int sendRequest(URL url, Session session, @Nullable ZonedDateTime ifModifiedSince); @Override int sendCertificateRequest(URL url, Login login); @Override int sendSignedPostAsGetRequest(URL url, Login login); @Override int sendSignedRequest(URL url, JSONBuilder claims, Login login); @Override int sendSignedRequest(URL url, JSONBuilder claims, Session session, KeyPair keypair); @Override JSON readJsonResponse(); @Override List<X509Certificate> readCertificates(); @Override void handleRetryAfter(String message); @Override @Nullable String getNonce(); @Override @Nullable URL getLocation(); @Override Optional<ZonedDateTime> getLastModified(); @Override Optional<ZonedDateTime> getExpiration(); @Override Collection<URL> getLinks(String relation); @Override void close();  }
@Test public void testReadCertificate() throws Exception { when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/pem-certificate-chain"); when(mockUrlConnection.getInputStream()).thenReturn(getClass().getResourceAsStream("/cert.pem")); List<X509Certificate> downloaded; try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; downloaded = conn.readCertificates(); } List<X509Certificate> original = TestUtils.createCertificate(); assertThat(original.size(), is(2)); assertThat(downloaded, not(nullValue())); assertThat(downloaded.size(), is(original.size())); for (int ix = 0; ix < downloaded.size(); ix++) { assertThat(downloaded.get(ix).getEncoded(), is(original.get(ix).getEncoded())); } verify(mockUrlConnection).getHeaderField("Content-Type"); verify(mockUrlConnection).getInputStream(); verifyNoMoreInteractions(mockUrlConnection); }
@Test(expected = AcmeProtocolException.class) public void testReadBadCertificate() throws Exception { byte[] brokenPem; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter w = new OutputStreamWriter(baos)) { for (X509Certificate cert : TestUtils.createCertificate()) { byte[] badCert = cert.getEncoded(); Arrays.sort(badCert); AcmeUtils.writeToPem(badCert, AcmeUtils.PemLabel.CERTIFICATE, w); } w.flush(); brokenPem = baos.toByteArray(); } when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/pem-certificate-chain"); when(mockUrlConnection.getInputStream()).thenReturn(new ByteArrayInputStream(brokenPem)); try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; conn.readCertificates(); } }