/**
 *  Copyright (c) 2006 by Know-Center, Graz, Austria 
 * 
 * This software is the confidential and proprietary information of Know-Center,
 * Graz, Austria. You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Know-Center.
 * 
 * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 * 
 * $Id: Main.java,v 1.5 2006/10/31 08:06:56 wprinz Exp $
 */
package at.knowcenter.wag.egov.egiz.commandline;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import at.knowcenter.wag.egov.egiz.PdfAS;
import at.knowcenter.wag.egov.egiz.PdfASID;
import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
import at.knowcenter.wag.egov.egiz.exceptions.ErrorCodeException;
import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
import at.knowcenter.wag.egov.egiz.framework.SignResult;
import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
import at.knowcenter.wag.egov.egiz.framework.VerificationFilter;
import at.knowcenter.wag.egov.egiz.framework.signators.BinarySignator_1_0_0;
import at.knowcenter.wag.egov.egiz.framework.signators.DetachedSignator_1_0_0;
import at.knowcenter.wag.egov.egiz.framework.signators.TextualSignator_1_0_0;
import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.TablePos;
import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory;
import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
import at.knowcenter.wag.egov.egiz.web.servlets.VerifyServlet;
/**
 * The main program entry point of the commandline tool.
 * 
 * @author wprinz
 */
public abstract class Main
{
  /**
   * Command line parameter setting the application mode sign|verify
   */
  protected static final String PARAMETER_MODE = "-mode";
  /**
   * Command line parameter setting the application to connect
   */
  protected static final String PARAMETER_CONNECTOR = "-connector";
  /**
   * Command line parameter setting the signature mode.
   */
  protected static final String PARAMETER_SIGNATURE_MODE = "-sigmode";
  /**
   * Command line parameter setting the signature type.
   */
  protected static final String PARAMETER_SIGNATURE_TYPE = "-sigtype";
  /**
   * Command line parameter setting the username
   */
  protected static final String PARAMETER_USER_NAME = "-username";
  /**
   * Command line parameter setting the users password
   */
  protected static final String PARAMETER_USER_PASSWORD = "-password";
  /**
   * Command line parameter selecting the position of the signature.
   */
  protected static final String PARAMETER_POS = "-pos";
  /**
   * Command line parameter selecting the signature which is going to be
   * verified.
   */
  protected static final String PARAMETER_VERIFY_WHICH = "-verify_which";
  /**
   * The application mode sign
   */
  public static final String VALUE_MODE_SIGN = "sign";
  /**
   * The application mode verify
   */
  public static final String VALUE_MODE_VERIFY = "verify";
  /**
   * The application mode sign
   */
  public static final String VALUE_SIGNATURE_MODE_BINARY = "binary";
  /**
   * The application mode verify
   */
  public static final String VALUE_SIGNATURE_MODE_TEXTUAL = "textual";
  /**
   * The application mode verify
   */
  public static final String VALUE_SIGNATURE_MODE_DETACHED = "detached";
  /**
   * The application mode verify
   */
  public static final String VALUE_SIGNATURE_MODE_DETACHED_TEXt = "detachedtextual";
  /**
   * The logger definition.
   */
  private static final Logger logger_ = ConfigLogger.getLogger(Main.class);
  /**
   * Main program entry point.
   * 
   * @param args
   *          The commandline arguments.
   * @throws IOException
   */
  public static void main(String[] args) throws IOException
  {
    // ConfigLogger.setLevel(Level.DEBUG);
    SettingsReader.initializeForCommandLine();
    PropertyConfigurator.configure(SettingsReader.CONFIG_PATH + "log4j.properties");
    try
    {
      // printUsage(System.out);
      String mode = null;
      String signature_mode = null;
      String connector = null;
      String signature_type = null;
      String user_name = null;
      String user_password = null;
      String pos_string = null;
      int verify_which = -1;
      String input = null;
      String output = null;
      // for (int i = 0; i < args.length; i++)
      // {
      // logger_.debug("arg[" + i + "] = " + args[i]);
      // }
      for (int i = 0; i < args.length; i++)
      {
        String cur_arg = args[i].trim();
        if (cur_arg.equals(PARAMETER_MODE))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_MODE);
            return;
          }
          mode = args[i];
          if (!checkMode(mode))
          {
            printUnrecognizedValue(PARAMETER_MODE, mode);
            return;
          }
          continue;
        }
        if (cur_arg.equals(PARAMETER_CONNECTOR))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_CONNECTOR);
            return;
          }
          connector = args[i];
          if (!checkConnector(connector))
          {
            printUnrecognizedValue(PARAMETER_CONNECTOR, connector);
            return;
          }
          continue;
        }
        if (cur_arg.equals(PARAMETER_SIGNATURE_MODE))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_SIGNATURE_MODE);
            return;
          }
          signature_mode = args[i];
          if (!checkSignatureMode(signature_mode))
          {
            printUnrecognizedValue(PARAMETER_SIGNATURE_MODE, signature_mode);
            return;
          }
          continue;
        }
        if (cur_arg.equals(PARAMETER_SIGNATURE_TYPE))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_SIGNATURE_TYPE);
            return;
          }
          signature_type = args[i];
          if (!checkSignatureType(signature_type))
          {
            printUnrecognizedValue(PARAMETER_SIGNATURE_TYPE, signature_type);
            return;
          }
          continue;
        }
        if (cur_arg.equals(PARAMETER_USER_NAME))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_USER_NAME);
            return;
          }
          user_name = args[i];
          continue;
        }
        if (cur_arg.equals(PARAMETER_USER_PASSWORD))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_USER_PASSWORD);
            return;
          }
          user_password = args[i];
          continue;
        }
        if (cur_arg.equals(PARAMETER_POS))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_POS);
            return;
          }
          pos_string = args[i];
          continue;
        }
        if (cur_arg.equals(PARAMETER_VERIFY_WHICH))
        {
          i++;
          if (i >= args.length)
          {
            printNoValue(PARAMETER_VERIFY_WHICH);
            return;
          }
          String str_verify_which = args[i];
          try
          {
            verify_which = Integer.parseInt(str_verify_which);
          }
          catch (NumberFormatException e)
          {
            printUnrecognizedValue(PARAMETER_VERIFY_WHICH, str_verify_which);
            return;
          }
          continue;
        }
        if (cur_arg.charAt(0) == '-')
        {
          printUnrecognizedOption(cur_arg);
          return;
        }
        if (input == null)
        {
          input = cur_arg;
          continue;
        }
        if (output == null)
        {
          output = cur_arg;
          continue;
        }
        printUnrecognizedAdditionalCommandlineArgument(cur_arg);
        return;
      }
      if (mode == null)
      {
        printMissingParameter("a mode", PARAMETER_MODE);
        return;
      }
      if (connector == null)
      {
        printMissingParameter("a connector", PARAMETER_CONNECTOR);
        return;
      }
      if (mode.equals(VALUE_MODE_SIGN))
      {
        if (signature_mode == null)
        {
          printMissingParameter("a signature mode", PARAMETER_SIGNATURE_MODE);
          return;
        }
        if (signature_type == null)
        {
          SettingsReader settings = SettingsReader.getInstance();
          String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
          signature_type = default_type;
        }
        if (user_name == null)
        {
          user_name = "";
          // printMissingParameter("a user name", PARAMETER_USER_NAME);
          // return;
        }
        if (user_password == null)
        {
          user_password = "";
          // printMissingParameter("a user password", PARAMETER_USER_PASSWORD);
          // return;
        }
      }
      if (input == null)
      {
        printMissing("an input document");
        return;
      }
      File file = new File(input);
      if (!file.exists())
      {
        System.err.println("The input file '" + input + "' doesn't exist.");
        return;
      }
      carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string);
    }
    catch (PresentableException e)
    {
      if (e instanceof ErrorCodeException)
      {
        ErrorCodeException ece = (ErrorCodeException) e;
        printErrorCodeException(ece);
      }
      else
      {
        System.err.println("PresentableException:");
        System.err.println(e.getMessage());
        logger_.debug(e.toString());
      }
    }
    finally
    {
      SettingsReader.clearTemporaryDirectory();
    }
  }
  /**
   * Carries out the actual command given via the commandline parameters.
   * 
   * 
   * This is simply the procedure that is executed after the commandline
   * parameters have been parsed successfully.
   * 
   * 
   * @param mode
   *          The operation mode (e.g. "sign", "verify").
   * @param signature_mode
   *          The signature mode (e.g. "binary", "textual").
   * @param connector
   *          The connector (e.g. "bku", "a1").
   * @param signature_type
   *          The signature type/profile. For signing only.
   * @param user_name
   *          The user name. For signing only.
   * @param user_password
   *          The user password. For signing only.
   * @param verify_which
   *          The number of the signature to be verified. For verifying only.
   * @param input
   *          The input file name.
   * @param output
   *          The output file name.
   * @throws PresentableException
   */
  protected static void carryOutCommand(final String mode,
      final String signature_mode, final String connector,
      final String signature_type, final String user_name,
      final String user_password, final int verify_which, final String input,
      String output, final String pos_string) throws PresentableException
  {
    File file = new File(input);
    byte[] input_bytes = null;
    try
    {
      FileInputStream fis = new FileInputStream(file);
      input_bytes = new byte[(int) file.length()];
      fis.read(input_bytes);
      fis.close();
    }
    catch (IOException e)
    {
      throw new PDFDocumentException(201);
    }
    if (mode.equals(VALUE_MODE_SIGN))
    {
      System.out.println("Signing...");
      PdfAS.applyStrictMode(input_bytes);
      TablePos pos = null;
      if (pos_string != null)
      {
        try
        {
          pos = PdfAS.parsePositionFromPosString(pos_string);
        }
        catch (PDFDocumentException e)
        {
          printUnrecognizedValue(PARAMETER_POS, pos_string);
          return;
        }
      }
      PdfASID algorithm = translateSignatureModeToPdfASID(signature_mode);
      // TODO MOA detached signing is not allowed at the commandline
      logger_.debug("Suggested sign algorithm = " + algorithm);
      if (connector.equals("moa"))
      {
        String msg = "Hinweis: Der MOA Detached Connector ist für die Kommandozeile nicht geeignet. Die Signatur wird daher im alten Base64 enveloping Format ausgeführt.";
        System.out.println(msg);
        logger_.warn(msg);
        if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY))
        {
          algorithm = BinarySignator_1_0_0.MY_ID;
        }
        if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL))
        {
          algorithm = TextualSignator_1_0_0.MY_ID;
        }
      }
      logger_.debug("Finally used sign algorithm = " + algorithm);
      SignResult sign_result = PdfAS.sign(algorithm, input_bytes, signature_type, connector, user_name, user_password, pos);
      try
      {
        if (output == null)
        {
          output = generateOutputFileNameFromInput(input, sign_result);
        }
        FileOutputStream fos = new FileOutputStream(output);
        fos.write(sign_result.getData());
        fos.close();
      }
      catch (IOException e)
      {
        throw new PDFDocumentException(205);
      }
      System.out.println("Signing was successful.");
    }
    else
    {
      System.out.println("Verifying...");
      VerificationFilter vf = new VerificationFilter();
      List signature_holders = null;
      String extension = VerifyServlet.extractExtension(input);
      if (extension != null && extension.equals("txt"))
      {
        try
        {
          String text = new String(input_bytes, "UTF-8");
          signature_holders = vf.extractSignaturesFromPlainText(text);
        }
        catch (UnsupportedEncodingException e)
        {
          throw new PresentableException(e);
        }
      }
      else
      {
        signature_holders = vf.extractSignaturesFromPdf(input_bytes);
      }
      if (signature_holders.isEmpty())
      {
        throw new PDFDocumentException(206);
      }
      List holders_to_verify = signature_holders;
      if (verify_which >= 0)
      {
        if (verify_which >= signature_holders.size())
        {
          throw new SignatureException(312, "The selected signature to be verified doesn't exist.");
        }
        SignatureHolder holder = (SignatureHolder) signature_holders.get(verify_which);
        holders_to_verify = new ArrayList();
        holders_to_verify.add(holder);
      }
      List results = PdfAS.verifySignatureHolders(holders_to_verify, connector);
      System.out.println("Verification results:");
      formatVerifyResults(results, System.out);
    }
  }
  /**
   * Generates a suitable output file name for the output regarding the type of
   * the sign_result.
   * 
   * @param input
   *          The input file name.
   * @param sign_result
   *          The sign result.
   * @return Returns the output file name.
   */
  protected static String generateOutputFileNameFromInput(String input,
      SignResult sign_result)
  {
    String output = input + "_out";
    if (sign_result.getMimeType().equals(DetachedSignator_1_0_0.MIME_TYPE))
    {
      output += ".xml";
    }
    else
    {
      output += ".pdf";
    }
    return output;
  }
  /**
   * Prints that the provided option was unrecognized.
   * 
   * @param option
   *          The unrecognized option.
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printUnrecognizedOption(final String option) throws PresentableException
  {
    System.err.println("Unrecognized option '" + option + "'.");
    printUsage(System.out);
  }
  /**
   * Prints that the provided value was unrecognized.
   * 
   * @param parameter
   *          The parameter, which is missing a value.
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printNoValue(final String parameter) throws PresentableException
  {
    System.err.println("The parameter " + parameter + " requires a value as next argument.");
    printUsage(System.out);
  }
  /**
   * Prints that the provided value was unrecognized.
   * 
   * @param value
   *          The unrecognized value.
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printUnrecognizedValue(final String parameter,
      final String value) throws PresentableException
  {
    System.err.println("The parameter " + parameter + " doesn't recognize the provided value '" + value + "'.");
    printUsage(System.out);
  }
  /**
   * Prints that the provided additional commandline argument was unrecognized.
   * 
   * @param argument
   *          The unrecognized argument.
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printUnrecognizedAdditionalCommandlineArgument(
      final String argument) throws PresentableException
  {
    System.err.println("Unrecognized additional commandline argument '" + argument + "'.");
    printUsage(System.out);
  }
  /**
   * Prints that a certain parameter was missing.
   * 
   * @param missing_term
   *          A description of the missing parameter ("e.g. a mode").
   * @param parameter
   *          The missing parameter itself (e.g. "-mode").
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printMissingParameter(final String missing_term,
      final String parameter) throws PresentableException
  {
    printMissing(missing_term + " ('" + parameter + "' parameter)");
  }
  /**
   * Prints that something is missing.
   * 
   * @param missing_term
   *          A descriptive message of the missing thing.
   * @throws PresentableException
   *           Forwarded exception.
   */
  protected static void printMissing(final String missing_term) throws PresentableException
  {
    System.err.println("Please specify " + missing_term + ".");
    printUsage(System.out);
  }
  /**
   * Prints out the ErrorCodeException in a descriptive form.
   * 
   * @param ece
   *          The ErrorCodeException to be printed.
   */
  protected static void printErrorCodeException(final ErrorCodeException ece)
  {
    if (ece instanceof PlaceholderException)
    {
      PlaceholderException phe = (PlaceholderException) ece;
      System.err.println("Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz. ");
    }
    System.err.println("Fehler " + ece.getErrorCode() + ": " + ece.getErrorCodeMessage());
    if (ece.hasExternalErrorMessage())
    {
      System.err.println("Externer Fehlergrund: " + ece.getExternalErrorCode() + ": " + ece.getExternalErrorMessage());
    }
    logger_.debug(ece.toString());
  }
  /**
   * Prints the usage text.
   * 
   * @param writer
   *          The writer to print the text to.
   * @throws PresentableException
   *           Forwarded exception.
   */
  public static void printUsage(PrintStream writer) throws PresentableException
  {
    writer.println("Usage: pdf-as [OPTIONS]  [output file]");
    writer.println("  Required OPTIONS:");
    writer.println("    " + PARAMETER_MODE + " <" + VALUE_MODE_SIGN + "|" + VALUE_MODE_VERIFY + ">");
    writer.println("      " + VALUE_MODE_SIGN + " ... signs a document");
    writer.println("      " + VALUE_MODE_VERIFY + " ... verifies a document");
    writer.print("    " + PARAMETER_CONNECTOR + " ");
    ConnectorInformation[] ci = ConnectorFactory.getConnectorInformationArray();
    for (int i = 0; i < ci.length; i++)
    {
      String id = ci[i].getIdentifier();
      if (!ConnectorFactory.isAvailableForCommandline(id))
      {
        continue;
      }
      writer.print(id);
      if (i < ci.length - 1)
      {
        writer.print("|");
      }
    }
    writer.println();
    for (int i = 0; i < ci.length; i++)
    {
      String id = ci[i].getIdentifier();
      if (!ConnectorFactory.isAvailableForCommandline(id))
      {
        continue;
      }
      writer.println("      " + id + " ... " + ci[i].getDescription());
    }
    writer.println("  OPTIONS for signation:");
    writer.println("    " + PARAMETER_SIGNATURE_MODE + " <" + VALUE_SIGNATURE_MODE_BINARY + "|" + VALUE_SIGNATURE_MODE_TEXTUAL + ">");
    writer.println("      " + VALUE_SIGNATURE_MODE_BINARY + " ... signs the complete binary document");
    writer.println("      " + VALUE_SIGNATURE_MODE_TEXTUAL + " ... signs only the textual portion of the document");
    writer.println("      " + VALUE_SIGNATURE_MODE_DETACHED + " ... signs the document using the binary mode and returns the xml signature of it.");
    writer.println("      " + VALUE_SIGNATURE_MODE_DETACHED_TEXt + " ... signs the document using the textual mode and returns the xml signature of it.");
    writer.print("    " + PARAMETER_SIGNATURE_TYPE + " <");
    SignatureTypes sig_types = SignatureTypes.getInstance();
    SettingsReader settings = SettingsReader.getInstance();
    List types_array = sig_types.getSignatureTypes();
    Iterator it = types_array.iterator();
    while (it.hasNext())
    {
      String type = (String) it.next();
      writer.print(type);
      if (it.hasNext())
      {
        writer.print("|");
      }
    }
    writer.println(">");
    writer.println("      ... [optional] the profile to be used. If omitted, the default");
    writer.println("          profile is used.");
    String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
    it = types_array.iterator();
    while (it.hasNext())
    {
      String type = (String) it.next();
      String descr_key = SignatureTypes.SIG_OBJ + type + "." + SignatureTypes.SIG_DESCR;
      String type_descr = settings.getValueFromKey(descr_key);
      writer.println("      " + type + " ... " + (type.equals(default_type) ? "(default) " : "") + type_descr);
    }
    writer.println("    " + PARAMETER_USER_NAME + "  ... [optional] the user name");
    writer.println("    " + PARAMETER_USER_PASSWORD + "  ... [optional] the user password");
    writer.println("    " + PARAMETER_POS + "  ... [optional] the position of the signature block");
    writer.println("      position has the format [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]");
    writer.println("      if not present default is set to  x:auto;y:auto;w:auto;p:auto;f:0");
    writer.println("      x_algo:='auto'     ... automatic positioning x");
    writer.println("              floatvalue ... absolute x must be >= 0");
    writer.println("      y_algo:='auto'     ... automatic positioning y");
    writer.println("              floatvalue ... absolute y must be >= 0");
    writer.println("      w_algo:='auto'     ... automatic width");
    writer.println("              floatvalue ... absolute width must be > 0");
    writer.println("      p_algo:='auto'     ... automatic last page");
    writer.println("              'new'      ... new page");
    writer.println("              intvalue   ... pagenumber must be > 0 if p>number of pages in document p-->handled like p:'new'");
    writer.println("      f_algo  floatvalue ... consider footerline must be >= 0 (only if y_algo is auto and p_algo is not 'new')");
    writer.println("  OPTIONS for verification:");
    writer.println("    " + PARAMETER_VERIFY_WHICH + "  ... [optional] zero based number of the signature");
    writer.println("      to be verified. If omitted, all signatures are verified.");
    writer.println("  Example usage:");
    writer.println("    pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " moa some_document.pdf");
    writer.println("    pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_VERIFY + " some_document.pdf_out.pdf");
  }
  /**
   * Checks the value for correctness.
   * 
   * @param mode
   *          The parameter's value.
   * @return Returns true, if the value is correct, false otherwise.
   */
  protected static boolean checkMode(String mode)
  {
    return mode.equals(VALUE_MODE_SIGN) || mode.equals(VALUE_MODE_VERIFY);
  }
  /**
   * Checks the value for correctness.
   * 
   * @param signature_mode
   *          The parameter's value.
   * @return Returns true, if the value is correct, false otherwise.
   */
  protected static boolean checkSignatureMode(String signature_mode)
  {
    return signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY) || signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL) || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED) || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXt);
  }
  /**
   * Checks the value for correctness.
   * 
   * @param connector
   *          The parameter's value.
   * @return Returns true, if the value is correct, false otherwise.
   * @throws ConnectorFactoryException
   *           F.e.
   */
  protected static boolean checkConnector(String connector) throws ConnectorFactoryException
  {
    return ConnectorFactory.isValidConnectorIdentifier(connector) && ConnectorFactory.isAvailableForCommandline(connector);
  }
  /**
   * Checks the value for correctness.
   * 
   * @param signature_type
   *          The parameter's value.
   * @return Returns true, if the value is correct, false otherwise.
   */
  protected static boolean checkSignatureType(String signature_type) throws SignatureTypesException
  {
    SignatureTypes sig_types = SignatureTypes.getInstance();
    List types_array = sig_types.getSignatureTypes();
    Iterator it = types_array.iterator();
    while (it.hasNext())
    {
      String type = (String) it.next();
      if (type.equals(signature_type))
      {
        return true;
      }
    }
    return false;
  }
  /**
   * Translates the commandline argument to a PDF-AS-ID.
   * 
   * @param signature_mode
   *          The signator mode commandline argument.
   * @return Returns the corresponding PDFASID.
   */
  protected static PdfASID translateSignatureModeToPdfASID(String signature_mode)
  {
    if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY))
    {
      return SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID;
    }
    if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL))
    {
      return SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID;
    }
    if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED))
    {
      return SignatorFactory.MOST_RECENT_DETACHED_SIGNATOR_ID;
    }
    if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXt))
    {
      return SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
    }
    return null;
  }
  /**
   * Formats the verification results.
   * 
   * @param results
   *          The List of SignatureResponse verification results.
   * @param writer
   *          The output sink to write the formatted text to.
   * @throws SettingNotFoundException
   *           Forwarded exception.
   */
  protected static void formatVerifyResults(List results, PrintStream writer) throws SettingNotFoundException
  {
    Iterator it = results.iterator();
    while (it.hasNext())
    {
      SignatureResponse result = (SignatureResponse) it.next();
      formatSignatureResponse(result, writer);
      if (it.hasNext())
      {
        writer.println();
      }
    }
  }
  /**
   * Formats the SignatureResponse.
   * 
   * @param result
   *          The SignatureResponse to be printed.
   * @param writer
   *          The output sink to write the formatted text to.
   * @throws SettingNotFoundException
   *           Forwarded exception.
   */
  public static void formatSignatureResponse(SignatureResponse result,
      PrintStream writer) throws SettingNotFoundException
  {
    writer.println("  Zertifikat:");
    writer.println("    Signator:     " + result.getX509SubjectName());
    writer.println("    Aussteller:   " + result.getX509IssuerName());
    writer.println("    Seriennummer: " + result.getX509SerialNumber());
    List public_properties = result.getPublicProperties();
    Iterator it = public_properties.iterator();
    while (it.hasNext())
    {
      String public_property = (String) it.next();
      writer.println("    Eigenschaft:  " + public_property);
    }
    writer.println("  Zertifikat-Check:");
    writer.println("    " + result.getCertificateCheckCode() + " - " + result.getCertificateCheckInfo());
    writer.println("  Signatur-Check:");
    writer.println("    " + result.getSignatureCheckCode() + " - " + result.getSignatureCheckInfo());
    writer.println("  Manifest-Check:");
    writer.println("    " + result.getSignatureManifestCheckCode() + " - " + result.getSignatureManifestCheckInfo());
  }
}