3939import java .time .temporal .ChronoUnit ;
4040import java .util .ArrayList ;
4141import java .util .HashMap ;
42- import java .util .LinkedHashMap ;
4342import java .util .List ;
4443import java .util .Map ;
45- import java .util .Objects ;
46- import java .util .Optional ;
4744import java .util .function .UnaryOperator ;
4845import java .util .stream .Collectors ;
4946
@@ -59,55 +56,42 @@ public class CertificateRipperClient {
5956 private static final String SYSTEM = "system" ;
6057
6158 private final ClientConfig clientConfig ;
59+ private final CertificateExtractingClient client ;
6260
6361 public CertificateRipperClient (ClientConfig clientConfig ) {
6462 this .clientConfig = clientConfig ;
63+ this .client = createClient ().build ();
6564 }
6665
6766 public CertificateHolder getCertificateHolder () {
6867 List <String > resolvedUrls = getUniqueUrls (clientConfig .getUrls ());
69- Map < String , List < X509Certificate >> urlsToCertificates = getCertificates (resolvedUrls );
68+ pingUrls (resolvedUrls );
7069
71- addSiblingsIfNeeded ( urlsToCertificates );
72- urlsToCertificates = filterCertificatesIfNeeded (urlsToCertificates , clientConfig .getCertificateType ());
70+ pingSiblings ( client . getCertificatesCollector () );
71+ Map < String , List < X509Certificate >> urlsToCertificates = filterCertificatesIfNeeded (client . getCertificatesCollector () , clientConfig .getCertificateType ());
7372 addSystemCertificatesIfNeeded (urlsToCertificates );
7473
7574 return new CertificateHolder (urlsToCertificates );
7675 }
7776
78- private Map <String , List <X509Certificate >> getCertificates (List <String > urls ) {
79- return urls .stream ().distinct ().parallel ()
80- .map (this ::getCertificates )
81- .filter (Optional ::isPresent )
82- .map (Optional ::get )
83- .collect (Collectors .collectingAndThen (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue , (key1 , key2 ) -> key1 , LinkedHashMap ::new ), HashMap ::new ));
84- }
85-
86- private Optional <Map .Entry <String , List <X509Certificate >>> getCertificates (String url ) {
87- try {
88- CertificateExtractingClient client = createClient (url ).build ();
89- List <X509Certificate > certificates = client .get (url );
90- return Optional .of (Map .entry (url , certificates ));
91- } catch (Exception e ) {
92- LOGGER .debug (String .format ("Could not extract from %s" , url ), e );
93- return Optional .empty ();
94- }
95- }
96-
97- private CertificateExtractingClient .Builder createClient (String url ) {
98- CertificateExtractingClient .Builder clientBuilder = createClient ();
99- URI uri = URI .create (url );
100- switch (uri .getScheme ()) {
101- case "wss" -> clientBuilder .withClientRunnable (new WebSocketClientRunnable ());
102- case "ftps" -> clientBuilder .withClientRunnable (new FtpsClientRunnable ());
103- case "smtps" -> clientBuilder .withClientRunnable (new SmtpClientRunnable ());
104- case "imaps" -> clientBuilder .withClientRunnable (new ImapClientRunnable ());
105- case "postgresql" -> clientBuilder .withClientRunnable (new PostgresClientRunnable ());
106- case "mysql" -> clientBuilder .withClientRunnable (new MySQLClientRunnable ());
107- default -> {}
108- }
77+ private void pingUrls (List <String > urls ) {
78+ urls .stream ().parallel ().forEach (url -> {
79+ var clientRunnable = switch (URI .create (url ).getScheme ()) {
80+ case "wss" -> WebSocketClientRunnable .getInstance ();
81+ case "ftps" -> FtpsClientRunnable .getInstance ();
82+ case "smtps" -> SmtpClientRunnable .getInstance ();
83+ case "imaps" -> ImapClientRunnable .getInstance ();
84+ case "postgresql" -> PostgresClientRunnable .getInstance ();
85+ case "mysql" -> MySQLClientRunnable .getInstance ();
86+ default -> null ;
87+ };
10988
110- return clientBuilder ;
89+ try {
90+ client .call (url , clientRunnable );
91+ } catch (Exception e ) {
92+ LOGGER .debug (String .format ("Could not extract from %s" , url ), e );
93+ }
94+ });
11195 }
11296
11397 private CertificateExtractingClient .Builder createClient () {
@@ -156,7 +140,7 @@ private List<String> getUniqueUrls(List<String> urls) {
156140 return uniqueUrls ;
157141 }
158142
159- private void addSiblingsIfNeeded (Map <String , List <X509Certificate >> urlsToCertificates ) {
143+ private void pingSiblings (Map <String , List <X509Certificate >> urlsToCertificates ) {
160144 if (!clientConfig .getResolveSiblings ()) {
161145 return ;
162146 }
@@ -167,24 +151,20 @@ private void addSiblingsIfNeeded(Map<String, List<X509Certificate>> urlsToCertif
167151 .setStyle (ProgressBarStyle .COLORFUL_UNICODE_BAR )
168152 .setTaskName ("Resolving sibling certificates" ).showSpeed ();
169153
170- List <String > urls = urlsToCertificates .values ().stream (). parallel ()
171- .flatMap (certificates -> UriUtils .getDnsNames (certificates ).stream ())
154+ List <String > urls = urlsToCertificates .values ().stream ()
155+ .flatMap (certificates -> UriUtils .extractHostsFromSAN (certificates ).stream ())
172156 .distinct ()
173157 .toList ();
174158
175- CertificateExtractingClient client = createClient (). build ();
176- Map < String , List < X509Certificate >> siblings = ProgressBar . wrap ( urls . stream (), pbb )
177- .map (url -> {
159+ ProgressBar . wrap ( urls . stream (), pbb )
160+ . parallel ( )
161+ .forEach (url -> {
178162 try {
179- return Map . entry ( url , client .get (url ) );
163+ client .call (url );
180164 } catch (Exception e ) {
181- return null ;
165+ LOGGER . debug ( String . format ( "Could not extract sibling certificate from %s" , url ), e ) ;
182166 }
183- })
184- .filter (Objects ::nonNull )
185- .collect (Collectors .collectingAndThen (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue , (key1 , key2 ) -> key1 , LinkedHashMap ::new ), HashMap ::new ));
186-
187- urlsToCertificates .putAll (siblings );
167+ });
188168 }
189169
190170 private void addSystemCertificatesIfNeeded (Map <String , List <X509Certificate >> urlsToCertificates ) {
@@ -200,7 +180,7 @@ private void addSystemCertificatesIfNeeded(Map<String, List<X509Certificate>> ur
200180
201181 Map <String , List <X509Certificate >> filterCertificatesIfNeeded (Map <String , List <X509Certificate >> urlsToCertificates , CertificateType type ) {
202182 return switch (type ) {
203- case ALL -> urlsToCertificates ;
183+ case ALL -> new HashMap <>( urlsToCertificates ) ;
204184 case LEAF -> filterCertificates (urlsToCertificates , certificates -> List .of (certificates .getFirst ()));
205185 case ROOT -> filterCertificates (urlsToCertificates , certificates -> List .of (certificates .getLast ()));
206186 case INTER -> filterCertificates (urlsToCertificates , certificates -> {
0 commit comments