ProductResender.java

  1. package gov.usgs.earthquake.distribution;

  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.InputStreamReader;
  5. import java.security.PrivateKey;
  6. import java.util.Iterator;
  7. import java.util.Map;
  8. import java.util.logging.Level;
  9. import java.util.logging.Logger;

  10. import gov.usgs.earthquake.aws.AwsProductSender;
  11. import gov.usgs.earthquake.product.Product;
  12. import gov.usgs.earthquake.product.io.IOUtil;
  13. import gov.usgs.earthquake.product.io.ObjectProductHandler;
  14. import gov.usgs.earthquake.product.io.ProductSource;
  15. import gov.usgs.util.CryptoUtils;
  16. import gov.usgs.util.FileUtils;

  17. /**
  18.  * A utility class to (re)send an existing product to pdl hubs.
  19.  *
  20.  * Mainly used when one server has not received a product, in order to
  21.  * redistribute the product.
  22.  */
  23. public class ProductResender {

  24.     private static final Logger LOGGER = Logger.getLogger(ProductResender.class
  25.             .getName());

  26.     /** Servers arguments */
  27.     public static final String SERVERS_ARGUMENT = "--servers=";
  28.     /** Batch arguments */
  29.     public static final String BATCH_ARGUMENT = "--batch";
  30.     /** Private Key Argument */
  31.     public static final String PRIVATE_KEY_ARGUMENT = "--privateKey=";

  32.     /**
  33.      * Command Line Interface to ProductResender.
  34.      *
  35.      * @param args CLI arguments
  36.      * @throws Exception if error occurs
  37.      */
  38.     public static void main(final String[] args) throws Exception {
  39.         // disable tracker
  40.         ProductTracker.setTrackerEnabled(false);

  41.         File inFile = null;
  42.         String inFormat = null;
  43.         String servers = null;
  44.         boolean binaryFormat = false;
  45.         boolean enableDeflate = true;
  46.         boolean batchMode = false;
  47.         PrivateKey privateKey = null;

  48.         for (String arg : args) {
  49.             if (arg.startsWith(IOUtil.INFILE_ARGUMENT)) {
  50.                 inFile = new File(arg.replace(IOUtil.INFILE_ARGUMENT, ""));
  51.             } else if (arg.startsWith(IOUtil.INFORMAT_ARGUMENT)) {
  52.                 inFormat = arg.replace(IOUtil.INFORMAT_ARGUMENT, "");
  53.             } else if (arg.startsWith(SERVERS_ARGUMENT)) {
  54.                 servers = arg.replace(SERVERS_ARGUMENT, "");
  55.             } else if (arg.equals(CLIProductBuilder.BINARY_FORMAT_ARGUMENT)) {
  56.                 binaryFormat = true;
  57.             } else if (arg.equals(CLIProductBuilder.DISABLE_DEFLATE)) {
  58.                 enableDeflate = false;
  59.             } else if (arg.equals(BATCH_ARGUMENT)) {
  60.                 batchMode = true;
  61.             } else if (arg.startsWith(PRIVATE_KEY_ARGUMENT)) {
  62.                 privateKey = CryptoUtils.readOpenSSHPrivateKey(
  63.                         FileUtils.readFile(new File(arg.replace(PRIVATE_KEY_ARGUMENT, ""))),
  64.                         null);
  65.                 if (privateKey == null) {
  66.                     LOGGER.warning("Unable to parse private key " + arg);
  67.                     System.exit(1);
  68.                 }
  69.             }
  70.         }

  71.         // read product
  72.         Product product = null;
  73.         if (!batchMode) {
  74.             ProductSource source = IOUtil.getProductSource(inFormat, inFile);
  75.             if (source != null) {
  76.                 product = ObjectProductHandler.getProduct(source);
  77.             }
  78.         }

  79.         ProductBuilder builder = new ProductBuilder();
  80.         builder.getProductSenders().addAll(
  81.                 CLIProductBuilder.parseServers(servers, 15000, binaryFormat,
  82.                         enableDeflate));
  83.         if (privateKey != null) {
  84.             // resign products
  85.             for (ProductSender sender : builder.getProductSenders()) {
  86.                 if (sender instanceof AwsProductSender) {
  87.                     AwsProductSender awsSender = (AwsProductSender) sender;
  88.                     awsSender.setPrivateKey(privateKey);
  89.                     awsSender.setSignProducts(true);;
  90.                 }
  91.             }
  92.         }

  93.         if ((!batchMode && product == null) || builder.getProductSenders().size() == 0) {
  94.             System.err.println("Usage: ProductResender --servers=SERVERLIST"
  95.                     + " --informat=(zip|directory|xml) --infile=FILE"
  96.                     + " [--binaryFormat] [--disableDeflate] [--batch]");
  97.             System.err.println("When using batch mode (--batch), the --infile argument is ignored.");
  98.             System.err.println("Files to send are read one per line from stdin.");
  99.             System.exit(CLIProductBuilder.EXIT_INVALID_ARGUMENTS);
  100.         }

  101.         builder.startup();

  102.         if (!batchMode) {
  103.             sendProduct(builder, product, batchMode);
  104.         } else {
  105.             // send batch
  106.             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  107.             String line = null;
  108.             while ((line = br.readLine()) != null) {
  109.                 inFile = new File(line);
  110.                 ProductSource source = IOUtil.getProductSource(inFormat, inFile);
  111.                 if (source != null) {
  112.                     product = ObjectProductHandler.getProduct(source);
  113.                 } else {
  114.                     System.err.println("ERROR: unable to load product from '" +
  115.                             inFile.getCanonicalPath() + "'");
  116.                     continue;
  117.                 }
  118.                 sendProduct(builder, product, batchMode);
  119.             }
  120.         }

  121.         // normal exit
  122.         builder.shutdown();
  123.         System.exit(0);
  124.     }

  125.     /**
  126.      * Sends product to builder
  127.      * @param builder ProductBuilder
  128.      * @param product Product
  129.      * @param batchMode bool
  130.      * @throws Exception if error occurs
  131.      */
  132.     protected static void sendProduct(final ProductBuilder builder,
  133.             final Product product, final boolean batchMode) throws Exception {
  134.         // extracted from CLIProductBuilder

  135.         // send the product
  136.         Map<ProductSender, Exception> sendExceptions = builder
  137.                 .sendProduct(product);

  138.         // handle any send exceptions
  139.         if (sendExceptions.size() != 0) {
  140.             Iterator<ProductSender> senders = sendExceptions.keySet()
  141.                     .iterator();
  142.             // log the exceptions
  143.             while (senders.hasNext()) {
  144.                 ProductSender sender = senders.next();
  145.                 if (sender instanceof SocketProductSender) {
  146.                     // put more specific information about socket senders
  147.                     SocketProductSender socketSender = (SocketProductSender) sender;
  148.                     LOGGER.log(
  149.                             Level.WARNING,
  150.                             "Exception sending product to "
  151.                                     + socketSender.getHost() + ":"
  152.                                     + socketSender.getPort(),
  153.                             sendExceptions.get(sender));
  154.                 } else {
  155.                     LOGGER.log(Level.WARNING, "Exception sending product "
  156.                             + sendExceptions.get(sender));
  157.                 }
  158.             }

  159.             if (sendExceptions.size() < builder.getProductSenders().size()) {
  160.                 LOGGER.warning("Partial failure sending product,"
  161.                         + " at least one sender accepted product."
  162.                         + " Check the tracker for more information.");
  163.                 // still output built product id
  164.                 System.out.println(product.getId().toString());
  165.                 if (batchMode) {
  166.                     // don't interrupt the batch
  167.                     return;
  168.                 }
  169.                 // but exit with partial failure
  170.                 System.exit(CLIProductBuilder.EXIT_PARTIALLY_SENT);
  171.             } else {
  172.                 LOGGER.severe("Total failure sending product");
  173.                 // still output built product id
  174.                 System.err.println("ERROR: " + product.getId().toString());
  175.                 if (batchMode) {
  176.                     // don't interrupt the batch
  177.                     return;
  178.                 }
  179.                 System.exit(CLIProductBuilder.EXIT_UNABLE_TO_SEND);
  180.             }

  181.         }

  182.         // otherwise output built product id
  183.         System.out.println(product.getId().toString());
  184.     }

  185. }