package org.icij.extract.spewer; import org.apache.commons.cli.ParseException; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.icij.extract.OutputType; import org.icij.extract.extractor.Extractor; import org.icij.net.http.PinnedHttpClientBuilder; import org.icij.task.Options; import org.icij.task.annotation.Option; import org.icij.task.annotation.OptionsClass; /** * A factory class for creating {@link Spewer} instances from given commandline option values. * * @since 1.0.0 * @author Matthew Caruana Galizia <mcaruana@icij.org> */ @Option(name = "outputType", description = "Set the output type. Either \"file\", \"stdout\" or \"solr\".", parameter = "type", code = "o") @Option(name = "indexType", description = "Specify the index type. For now, the only valid value is " + "\"solr\" (the default).", parameter = "type") @Option(name = "indexAddress", description = "Index core API endpoint address.", code = "s", parameter = "url") @Option(name = "indexServerCertificate", description = "The index server's public certificate, used for" + " certificate pinning. Supported formats are PEM, DER, PKCS #12 and JKS.", parameter = "path") @Option(name = "indexVerifyHost", description = "Verify the index server's public certificate against " + "the specified host. Use the wildcard \"*\" to disable verification.", parameter = "hostname") @OptionsClass(SolrSpewer.class) @OptionsClass(MergingSolrSpewer.class) @OptionsClass(FileSpewer.class) @OptionsClass(PrintStreamSpewer.class) public abstract class SpewerFactory { /** * Create a new {@link Spewer} by parsing the given commandline parameters. * * @param options the options to parse * @return A new spewer configured according to the given parameters. * @throws ParseException When the commandline parameters cannot be read. */ public static Spewer createSpewer(final Options<String> options) throws ParseException { final OutputType outputType = options.get("outputType").parse().asEnum(OutputType::parse) .orElse(OutputType.STDOUT); final FieldNames fields = new FieldNames().configure(options); final Spewer spewer; if (OutputType.SOLR == outputType) { spewer = createSolrSpewer(options, fields); } else if (OutputType.REST == outputType) { spewer = createRESTSpewer(options, fields); } else if (OutputType.FILE == outputType) { spewer = new FileSpewer(fields); } else { spewer = new PrintStreamSpewer(System.out, fields); } spewer.configure(options); return spewer; } private static CloseableHttpClient createHttpClient(final Options<String> options) { return PinnedHttpClientBuilder.createWithDefaults() .setVerifyHostname(options.get("indexVerifyHost").value().orElse(null)) .pinCertificate(options.get("indexServerCertificate").value().orElse(null)) .build(); } private static RESTSpewer createRESTSpewer(final Options<String> options, final FieldNames fields) { return new RESTSpewer(fields, createHttpClient(options), options.get("indexAddress").parse().asURI() .orElseThrow(IllegalArgumentException::new)); } /** * Create a new {@link SolrSpewer} by parsing the given options. * * @param options the options to parse * @return A new spewer configured according to the given parameters. */ private static SolrSpewer createSolrSpewer(final Options<String> options, final FieldNames fields) { final Extractor.EmbedHandling handling = options.get("embedHandling").parse().asEnum(Extractor .EmbedHandling::parse).orElse(Extractor.EmbedHandling.getDefault()); // Calling #close on the SolrSpewer later on automatically closes the HTTP client. final SolrClient solrClient = new HttpSolrClient.Builder(options.get("indexAddress").value().orElse ("http://127.0.0.1:8983/solr/")) .withHttpClient(createHttpClient(options)) .build(); if (Extractor.EmbedHandling.SPAWN == handling) { return new MergingSolrSpewer(solrClient, fields); } return new SolrSpewer(solrClient, fields); } }