From 61a2d23ef72630934c603fe9ffb96ebebff6ee09 Mon Sep 17 00:00:00 2001
From: netconomy <netconomy@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>
Date: Thu, 29 Nov 2007 12:00:22 +0000
Subject: PDF-AS API

git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@233 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c
---
 src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java   |   39 +
 src/main/java/at/gv/egiz/pdfas/api/PdfAs.java      |  123 +++
 .../egiz/pdfas/api/analyze/AnalyzeParameters.java  |   69 ++
 .../gv/egiz/pdfas/api/analyze/AnalyzeResult.java   |   30 +
 .../at/gv/egiz/pdfas/api/commons/Constants.java    |   77 ++
 .../pdfas/api/commons/SignatureInformation.java    |   97 ++
 .../egiz/pdfas/api/commons/SignatureProfile.java   |   29 +
 .../egiz/pdfas/api/exceptions/PdfAsException.java  |   78 ++
 .../java/at/gv/egiz/pdfas/api/io/DataSink.java     |   75 ++
 .../java/at/gv/egiz/pdfas/api/io/DataSource.java   |   74 ++
 .../java/at/gv/egiz/pdfas/api/io/FileBased.java    |   31 +
 .../java/at/gv/egiz/pdfas/api/io/TextBased.java    |   30 +
 .../at/gv/egiz/pdfas/api/sign/SignParameters.java  |  173 ++++
 .../java/at/gv/egiz/pdfas/api/sign/SignResult.java |   49 +
 .../egiz/pdfas/api/sign/pos/SignaturePosition.java |   52 +
 .../pdfas/api/sign/pos/SignaturePositioning.java   |  189 ++++
 .../api/sign/pos/axis/AbsoluteAxisAlgorithm.java   |   35 +
 .../pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java |   14 +
 .../pdfas/api/sign/pos/axis/AxisAlgorithm.java     |   14 +
 .../api/sign/pos/page/AbsolutePageAlgorithm.java   |   37 +
 .../pdfas/api/sign/pos/page/AutoPageAlgorithm.java |   20 +
 .../pdfas/api/sign/pos/page/NewPageAlgorithm.java  |   14 +
 .../pdfas/api/sign/pos/page/PageAlgorithm.java     |   14 +
 .../gv/egiz/pdfas/api/verify/SignatureCheck.java   |   31 +
 .../api/verify/VerifyAfterAnalysisParameters.java  |  117 +++
 .../gv/egiz/pdfas/api/verify/VerifyParameters.java |  183 ++++
 .../at/gv/egiz/pdfas/api/verify/VerifyResult.java  |   97 ++
 .../at/gv/egiz/pdfas/api/verify/VerifyResults.java |   27 +
 .../java/at/gv/egiz/pdfas/commandline/Main.java    | 1071 ++++++++++++++++++++
 .../gv/egiz/pdfas/framework/ConnectorFactory.java  |   12 +-
 .../egiz/pdfas/framework/ConnectorParameters.java  |   85 ++
 .../framework/signator/SignatorInformation.java    |   20 +
 .../at/gv/egiz/pdfas/impl/api/CheckHelper.java     |  213 ++++
 .../at/gv/egiz/pdfas/impl/api/PdfAsObject.java     |  317 ++++++
 .../java/at/gv/egiz/pdfas/impl/api/PosHelper.java  |   79 ++
 .../pdfas/impl/api/analyze/AnalyzeResultImpl.java  |   47 +
 .../pdfas/impl/api/commons/DataSinkAdapter.java    |   83 ++
 .../impl/api/commons/DataSourceApiAdapter.java     |   85 ++
 .../impl/api/commons/PdfDataSourceAdapter.java     |   52 +
 .../api/commons/SignatureInformationAdapter.java   |   87 ++
 .../impl/api/commons/SignatureProfileImpl.java     |   56 +
 .../impl/api/commons/TextDataSourceAdapter.java    |   52 +
 .../api/sign/ActualSignaturePositionAdapter.java   |   73 ++
 .../egiz/pdfas/impl/api/sign/SignResultImpl.java   |   75 ++
 .../pdfas/impl/api/verify/SignatureCheckImpl.java  |   51 +
 .../pdfas/impl/api/verify/VerifyResultAdapter.java |  126 +++
 .../pdfas/impl/api/verify/VerifyResultsImpl.java   |   38 +
 .../pdfas/impl/input/helper/DataSourceHelper.java  |   17 +-
 .../impl/signator/IncrementalUpdateHelper.java     |    8 +-
 .../signator/binary/BinarySignatorInformation.java |   19 +
 .../impl/signator/binary/BinarySignator_1_0_0.java |    2 +
 .../textual/TextualSignatorInformation.java        |   19 +-
 .../signator/textual/TextualSignator_1_0_0.java    |    4 +-
 .../at/gv/egiz/pdfas/io/ByteArrayDataSink.java     |   87 ++
 .../at/gv/egiz/pdfas/io/ByteArrayDataSource.java   |   95 ++
 .../at/gv/egiz/pdfas/io/FileBasedDataSink.java     |   96 ++
 .../at/gv/egiz/pdfas/io/FileBasedDataSource.java   |  121 +++
 .../pdfas/io/FileBasedTextBasedDataSource.java     |  103 ++
 .../egiz/pdfas/io/StringTextBasedDataSource.java   |   96 ++
 .../java/at/knowcenter/wag/egov/egiz/PdfAS.java    |   41 +-
 .../wag/egov/egiz/cfg/SettingsReader.java          |   36 +-
 .../knowcenter/wag/egov/egiz/commandline/Main.java |    4 +-
 .../egov/egiz/exceptions/PresentableException.java |   42 +-
 .../wag/egov/egiz/pdf/AbsoluteTextSignature.java   |    8 +
 .../wag/egov/egiz/pdf/ActualTablePos.java          |   22 +
 .../wag/egov/egiz/pdf/BinarySignature.java         |    8 +
 .../egiz/pdf/IncrementalUpdateInformation.java     |    5 +
 .../wag/egov/egiz/sig/SignatureResponse.java       |   12 +
 .../wag/egov/egiz/sig/SignatureTypes.java          |   10 +
 .../egov/egiz/sig/connectors/ConnectorChooser.java |   21 +-
 .../egov/egiz/sig/connectors/TemplateReplaces.java |   10 +
 .../egov/egiz/sig/connectors/bku/BKUHelper.java    |   51 +
 .../sig/connectors/bku/DetachedBKUConnector.java   |   17 +-
 .../connectors/bku/LocRefDetachedBKUConnector.java |    7 +-
 .../bku/MultipartDetachedBKUConnector.java         |    5 +-
 .../connectors/moa/DetachedLocRefMOAConnector.java |    5 +-
 .../moa/MOASoapWithAttachmentConnector.java        |   64 +-
 .../wag/egov/egiz/web/servlets/DataURLServlet.java |   19 +-
 78 files changed, 5380 insertions(+), 114 deletions(-)
 create mode 100644 src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/PdfAs.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/commandline/Main.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
 create mode 100644 src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
 create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java

(limited to 'src')

diff --git a/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java b/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java
new file mode 100644
index 0000000..bc6f89d
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java
@@ -0,0 +1,39 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas;
+
+import java.io.File;
+
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.impl.api.PdfAsObject;
+
+/**
+ * Main factory for creating a PDF-AS API Instance (PdfAs Interface).
+ * 
+ * @see PdfAs
+ * 
+ * @author wprinz
+ */
+public class PdfAsFactory
+{
+  /**
+   * Creates a PDF-AS API instance for the given work directory.
+   * 
+   * @param workDirectory
+   *          The work directory.
+   * 
+   * @return Returns an instance of the PDF-AS API.
+   * @throws IllegalArgumentException
+   *           Thrown, if the workDirectory doesn't exist.
+   * @throws PdfAsException
+   *           Thrown, if the work directory does not meet its requirements, or
+   *           if the config file is invalid.
+   */
+  public static PdfAs createPdfAs(File workDirectory) throws PdfAsException
+  {
+    return new PdfAsObject(workDirectory);
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java b/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java
new file mode 100644
index 0000000..4a8a0e0
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java
@@ -0,0 +1,123 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
+import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
+import at.gv.egiz.pdfas.api.commons.SignatureProfile;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.api.verify.VerifyResults;
+
+/**
+ * The PDF-AS API main interface.
+ * 
+ * <p>
+ * Create an Object implementing this interface using the proper factory.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface PdfAs
+{
+
+  /**
+   * Signs a PDF document using PDF-AS.
+   * 
+   * @param signParameters
+   *          The sign parameters.
+   * @return Returns the signed document plus additional information.
+   * @throws PdfAsException
+   *           Thrown, if an error occurs.
+   * 
+   * @see SignParameters
+   * @see SignResult
+   */
+  public SignResult sign(SignParameters signParameters) throws PdfAsException;
+
+  /**
+   * Verifies a document with (potentially multiple) PDF-AS signatures.
+   * 
+   * @param verifyParameters
+   *          The verify parameters.
+   * @return Returns the verification results.
+   * @throws PdfAsException
+   *           Thrown, if an error occurs.
+   * 
+   * @see VerifyParameters
+   * @see VerifyResults
+   * @see VerifyResult
+   */
+  public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException;
+
+  /**
+   * Analyzes a document for signatures and returns a verify-able list of such.
+   * 
+   * @param analyzeParameters
+   *          The analyzation parameters.
+   * @return Returns a list of verify-able signatures that were found in the
+   *         document.
+   * @throws PdfAsException
+   *           Thrown on error.
+   * 
+   * @see AnalyzeParameters
+   * @see AnalyzeResult
+   * @see {@link #verify(AnalyzeResult)}
+   */
+  public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException;
+
+  /**
+   * Verifies a list of signatures that have been analyzed previously.
+   * 
+   * @param verifyAfterAnalysisParameters The parameters.
+   * 
+   * @return Returns the verification results.
+   * @throws PdfAsException
+   *           Thrown on error.
+   * 
+   * @see AnalyzeResult
+   * @see VerifyAfterAnalysisParameters
+   * @see VerifyResults
+   * @see VerifyResult
+   * @see {@link #analyze(AnalyzeParameters)}
+   */
+  public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException;
+
+  /**
+   * Reloads the configuration from the work directory.
+   * 
+   * @throws PdfAsException
+   *           Thrown, if an error occurs.
+   */
+  public void reloadConfig() throws PdfAsException;
+
+  /**
+   * Returns the list of information objects about the profiles available in the
+   * configuration.
+   * 
+   * <p>
+   * Note: Currently the profile information consists of the profile Id and the
+   * MOA Key Id only.
+   * </p>
+   * <p>
+   * Note: In near future the profile management will be moved out of the config
+   * file into an API class representation of the profiles which may render this
+   * (and related) methods obsolete.
+   * </p>
+   * 
+   * @return Returns the list of {@link SignatureProfile} objects with
+   *         information about the profiles available in the configuration.
+   * @throws PdfAsException
+   *           Thrown on error.
+   * 
+   * @see SignatureProfile
+   */
+  public List getProfileInformation() throws PdfAsException;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java
new file mode 100644
index 0000000..0ab854c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java
@@ -0,0 +1,69 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.analyze;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Parameter object that holds the analyze parameters.
+ * 
+ * @author wprinz
+ */
+public class AnalyzeParameters
+{
+
+  /**
+   * The document to be analyzed.
+   */
+  protected DataSource document = null;
+
+  /**
+   * The mode of operation how the document is analyzed.
+   * 
+   * <p>
+   * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for
+   * binary signatures only (very fast). Or may be
+   * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi
+   * conservative (optimized) text and binary verification (slow). Or may be
+   * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full
+   * conservative text and binary verification (very slow).
+   * </p>
+   */
+  protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+  /**
+   * @return the document
+   */
+  public DataSource getDocument()
+  {
+    return this.document;
+  }
+
+  /**
+   * @param document the document to set
+   */
+  public void setDocument(DataSource document)
+  {
+    this.document = document;
+  }
+
+  /**
+   * @return the verifyMode
+   */
+  public String getVerifyMode()
+  {
+    return this.verifyMode;
+  }
+
+  /**
+   * @param verifyMode the verifyMode to set
+   */
+  public void setVerifyMode(String verifyMode)
+  {
+    this.verifyMode = verifyMode;
+  }
+
+  
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java
new file mode 100644
index 0000000..098f309
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java
@@ -0,0 +1,30 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.analyze;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+
+/**
+ * The result of an analyze operation, which is a list of verifyable signatures.
+ * 
+ * @author wprinz
+ * 
+ */
+public interface AnalyzeResult
+{
+  /**
+   * Returns the list of found signatures.
+   * 
+   * @return Returns a list of {@link SignatureInformation} objects representing all
+   *         found signatures.
+   * @throws PdfAsException
+   *           Thrown on error.
+   * 
+   * @see SignatureInformation
+   */
+  public List getSignatures() throws PdfAsException;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
new file mode 100644
index 0000000..e8ebc16
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
@@ -0,0 +1,77 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+/**
+ * Contains commonly used constants.
+ * 
+ * @author wprinz
+ */
+public final class Constants
+{
+
+  /**
+   * Hidden default constructor.
+   */
+  private Constants()
+  {
+    // empty
+  }
+
+  /**
+   * A binary signature.
+   */
+  public static String SIGNATURE_TYPE_BINARY = "binary";
+
+  /**
+   * A textual signature.
+   */
+  public static String SIGNATURE_TYPE_TEXTUAL = "textual";
+
+  /**
+   * A "detached" textual signature.
+   * 
+   * <p>
+   * The document text is signed, but instead of returning the pdf with the signature block,
+   * the sign result XML of the connector is returned.
+   * </p>
+   */
+  public static String SIGNATURE_TYPE_DETACHEDTEXTUAL = "detachedtextual";
+
+  /**
+   * The signature device moa.
+   */
+  public static String SIGNATURE_DEVICE_MOA = "moa";
+
+  /**
+   * The signature device bku.
+   */
+  public static String SIGNATURE_DEVICE_BKU = "bku";
+
+  /**
+   * Only binary signatures are verified.
+   */
+  public static String VERIFY_MODE_BINARY_ONLY = "binaryOnly";
+
+  /**
+   * Binary and textual signatures are verified with time optimization.
+   * 
+   * <p>
+   * This mode of operation tries to minimize the numbers of text extractions,
+   * which are very time intensive, at the cost of some rare cases, in which some
+   * signatures may not be found.
+   * </p>
+   */
+  public static String VERIFY_MODE_SEMI_CONSERVATIVE = "semiConservative";
+
+  /**
+   * Binary and textual signatures are verified.
+   */
+  public static String VERIFY_MODE_FULL_CONSERVATIVE = "fullConservative";
+
+  /**
+   * All signatures are verified.
+   */
+  public static int VERIFY_ALL = -1;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java
new file mode 100644
index 0000000..d8c2a34
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java
@@ -0,0 +1,97 @@
+/**
+ * <copyright> Copyright (c) 2006 by Know-Center, Graz, Austria </copyright>
+ * 
+ * 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: SignatureHolder.java,v 1.3 2006/10/11 07:57:58 wprinz Exp $
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Holds the information of one found signature block, which is the signed data
+ * and the corresponding signature information.
+ * 
+ * @author wprinz
+ */
+public interface SignatureInformation
+{
+  /**
+   * Returns the type of this signature (binary/textual).
+   * 
+   * <p>
+   * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+   * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+   * </p>
+   * 
+   * @return Returns the type of this signature (binary/textual).
+   */
+  public String getSignatureType();
+
+  /**
+   * Returns the DataSource providing the data that was signed.
+   * 
+   * <p>
+   * Note that this is the signed data as sent to the verification device by
+   * PDF-AS. The verification device (e.g. MOA) may perform several other
+   * transformations on the data before feeding it to the signature hash
+   * function. To get the actual hashed data use the ReturnHashInputData mechanism (which is very slow).
+   * </p>
+   * 
+   * @return Returns the DataSource providing the data that was signed.
+   * 
+   * @see at.gv.egiz.pdfas.api.verify.VerifyParameters#setReturnHashInputData(boolean)
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getHashInputData()
+   * 
+   */
+  public DataSource getSignedData();
+
+  /**
+   * Returns the certificate of the signer.
+   * 
+   * <p>
+   * Information like subject name, issuer name or serial number can be
+   * retrieved form this certificate.
+   * </p>
+   * 
+   * @return Returns the certificate of the signer.
+   */
+  public X509Certificate getSignerCertificate();
+
+  /**
+   * Returns the signing time, which is the time when the signature was created.
+   * 
+   * @return Returns the signing time, which is the time when the signature was
+   *         created.
+   */
+  public Date getSigningTime();
+
+  /**
+   * Returns additional, internal information about the found signature.
+   * 
+   * <p>
+   * Note that this provides a way for developers to gather core information
+   * about the signature. What information is returned strongly depends on the
+   * core implementation.
+   * </p>
+   * 
+   * @return Returns additional, internal information about the signature. Null
+   *         means that no additional information is available.
+   */
+  public Object getInternalSignatureInformation();
+
+}
\ No newline at end of file
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
new file mode 100644
index 0000000..52bd27f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
@@ -0,0 +1,29 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+/**
+ * Definition of a signature profile.
+ * 
+ * @author wprinz
+ */
+public interface SignatureProfile
+{
+  // TODO: the full profile information will be implemented in future
+
+  /**
+   * Returns the profile id.
+   * 
+   * @return Returns the profile id.
+   */
+  public String getProfileId();
+
+  /**
+   * Returns the MOA KeyIdentifier.
+   * 
+   * @return Returns the MOA KeyIdentifier.
+   */
+  public String getMOAKeyIdentifier();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java b/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java
new file mode 100644
index 0000000..2986f81
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java
@@ -0,0 +1,78 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.exceptions;
+
+/**
+ * This exception is the base for all PDF-AS exceptions.
+ * 
+ * <p>
+ * Every PDF-AS Exception has an error code.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public abstract class PdfAsException extends Exception
+{
+  /**
+   * The error code.
+   */
+  protected int errorCode = -1;
+
+  /**
+   * Constructor.
+   * 
+   * @param errorCode
+   *          The error code.
+   * @param message
+   *          The detail message.
+   */
+  public PdfAsException(int errorCode, String message)
+  {
+    super(message);
+
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Constructor.
+   * 
+   * @param errorCode
+   *          The error code.
+   * @param message
+   *          The detail message.
+   * @param cause
+   *          The cause.
+   */
+  public PdfAsException(int errorCode, String message, Throwable cause)
+  {
+    super(message, cause);
+
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Constructor.
+   * 
+   * @param errorCode
+   *          The error code.
+   * @param cause
+   *          The cause.
+   */
+  public PdfAsException(int errorCode, Throwable cause)
+  {
+    super(cause);
+
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Returns the error code of this exception.
+   * 
+   * @return Returns the error code of this exception.
+   */
+  public int getErrorCode()
+  {
+    return this.errorCode;
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java b/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java
new file mode 100644
index 0000000..0136cf7
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Output document data sink.
+ * 
+ * <p>
+ * Actually, the DataSink can be seen as a factory for creating OutputStreams
+ * with mime type and character encoding provided. This allows the API user to
+ * decide how data is to be stored (e.g. in a file, in a byte array, etc.).
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface DataSink
+{
+  /**
+   * Creates an OutputStream for binary data.
+   * 
+   * <p>
+   * Note that the stream may be written only once. Creating another stream
+   * overwrites the existing one.
+   * </p>
+   * 
+   * @param mimeType
+   *          The mime type of the output data.
+   * @return Returns the created output stream.
+   * @throws IOException
+   *           Thrown if the stream cannot be created.
+   */
+  public OutputStream createOutputStream(String mimeType) throws IOException;
+
+  /**
+   * Creates an OutputStream for character data.
+   * 
+   * <p>
+   * This is basically the same as {@link #createOutputStream(String)}, but
+   * allows to specify the character encoding.
+   * </p>
+   * 
+   * @param mimeType
+   *          The mime type of the output data.
+   * @param characterEncoding
+   *          The character encoding of the data.
+   * @return Returns the created output stream.
+   * @throws IOException
+   *           Thrown if the stream cannot be created.
+   */
+  public OutputStream createOutputStream(String mimeType, String characterEncoding) throws IOException;
+
+  /**
+   * Returns the mime type of the data stream.
+   * 
+   * <p>
+   * This is only valid after a stream has been created.
+   * </p>
+   * 
+   * @return Returns the mime type of the data stream.
+   */
+  public String getMimeType();
+
+  /**
+   * Returns the character encoding of the data stream.
+   * 
+   * <p>
+   * This is only valid after a stream has been created. Null means that no
+   * character encoding was specified for the data (e.g. if the data is binary).
+   * </p>
+   * 
+   * @return Returns the character encoding of the data stream.
+   */
+  public String getCharacterEncoding();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java b/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java
new file mode 100644
index 0000000..bd8e0db
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java
@@ -0,0 +1,74 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.InputStream;
+
+/**
+ * Input document data source.
+ * 
+ * <p>
+ * This allows the holder of the data to decide how the data is to be stored (e.g. in a File or in a byte array).
+ * </p>
+ * 
+ * @author wprinz
+ * 
+ */
+public interface DataSource
+{
+  /**
+   * Creates a new InputStream that allows to read out the document's binary
+   * data from the beginning.
+   * 
+   * @return Returns the InputStream with the binary data.
+   */
+  public InputStream createInputStream();
+
+  /**
+   * Returns the length (number of bytes) of the stream.
+   * 
+   * @return Returns the length (number of bytes) of the stream.
+   */
+  public int getLength();
+
+  /**
+   * Returns the data of this DataSource as a byte array for random read only access.
+   * 
+   * <p>
+   * Calling this method indicates that you need a byte array for random
+   * <strong>read only</strong> access. The DataSource implementation should of
+   * course cache this byte array to avoid too much memory usage.
+   * </p>
+   * <p>
+   * Performance analysis has shown that the libraries internally convert the
+   * streams to byte arrays and that file system access is very slow.
+   * </p>
+   * <p>
+   * Never write to this byte array!
+   * </p>
+   * 
+   * @return Returns the data of this DataSource as a byte array for random read only access.
+   */
+  public byte[] getAsByteArray();
+
+  /**
+   * Returns the mime type of the data.
+   * 
+   * @return Returns the mime type of the data.
+   */
+  public String getMimeType();
+
+  /**
+   * Returns the character encoding of the data.
+   * 
+   * <p>
+   * This makes only sense for character based mime types.
+   * </p>
+   * 
+   * @return Returns the character encoding of the data or null if no encoding
+   *         is applicable (e.g. if the data is binary).
+   */
+  public String getCharacterEncoding();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java b/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java
new file mode 100644
index 0000000..555b630
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java
@@ -0,0 +1,31 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.File;
+
+/**
+ * Tells that the IO element (DataSink or DataSource) is backed by a file in the local file system.
+ * 
+ * <p>
+ * This is a hint that may be used by PDF-AS to optimize data access.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface FileBased
+{
+  
+  /**
+   * Returns the File "behind" this io element.
+   * 
+   * <p>
+   * This is usually used to determine the file name itself.
+   * </p>
+   * 
+   * @return Returns the File "behind" this io element.
+   */
+  public File getFile ();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java b/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java
new file mode 100644
index 0000000..68b5729
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java
@@ -0,0 +1,30 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.io;
+
+/**
+ * Tells, that the IO Element (DataSink - but mostly DataSource) is based upon
+ * character data.
+ * 
+ * <p>
+ * This can be used to retrieve the character text directly with the correct
+ * encoding etc.
+ * </p>
+ * <p>
+ * This makes most sense for text DataSources.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface TextBased
+{
+
+  /**
+   * Returns the text.
+   * 
+   * @return Returns the text.
+   */
+  public String getText();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java b/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
new file mode 100644
index 0000000..cc59cbd
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
@@ -0,0 +1,173 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+
+/**
+ * Parameter object that holds the sign parameters.
+ * 
+ * @author wprinz
+ */
+public class SignParameters
+{
+  /**
+   * The document to be signed.
+   * 
+   * <p>
+   * The DataSource implementation encapsulates the actual representaion of the
+   * data. E.g. the DataSource may be File based or byte array based. See
+   * package at.gv.egiz.pdfas.framework.input and at.gv.pdfas.impl.input
+   * </p>
+   */
+  protected DataSource document = null;
+
+  /**
+   * The type of the signature.
+   * 
+   * <p>
+   * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+   * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+   * </p>
+   */
+  protected String signatureType = Constants.SIGNATURE_TYPE_BINARY;
+
+  /**
+   * The signature device to perform the actual signature.
+   * 
+   * <p>
+   * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+   * {@link Constants#SIGNATURE_DEVICE_BKU}.
+   * </p>
+   */
+  protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+  /**
+   * The signature profile identifier identifying the profile to be used in the
+   * config file.
+   * 
+   * <p>
+   * Note: In near future it will be possible to provide a full specified
+   * profile here instead of the profile id.
+   * </p>
+   */
+  protected String signatureProfileId = null;;
+
+  /**
+   * The signature position. Consult the PDF-AS documentation section
+   * Commandline.
+   */
+  protected SignaturePositioning signaturePositioning = null;
+
+  /**
+   * The output DataSink that will receive the signed document.
+   */
+  protected DataSink output = null;
+
+  /**
+   * @return the document
+   */
+  public DataSource getDocument()
+  {
+    return document;
+  }
+
+  /**
+   * @param document
+   *          the document to set
+   */
+  public void setDocument(DataSource document)
+  {
+    this.document = document;
+  }
+
+  /**
+   * @return the signatureType
+   */
+  public String getSignatureType()
+  {
+    return signatureType;
+  }
+
+  /**
+   * @param signatureType
+   *          the signatureType to set
+   */
+  public void setSignatureType(String signatureType)
+  {
+    this.signatureType = signatureType;
+  }
+
+  /**
+   * @return the signatureDevice
+   */
+  public String getSignatureDevice()
+  {
+    return signatureDevice;
+  }
+
+  /**
+   * @param signatureDevice
+   *          the signatureDevice to set
+   */
+  public void setSignatureDevice(String signatureDevice)
+  {
+    this.signatureDevice = signatureDevice;
+  }
+
+  /**
+   * @return the signatureProfileId
+   */
+  public String getSignatureProfileId()
+  {
+    return signatureProfileId;
+  }
+
+  /**
+   * @param signatureProfileId
+   *          the signatureProfileId to set
+   */
+  public void setSignatureProfileId(String signatureProfileId)
+  {
+    this.signatureProfileId = signatureProfileId;
+  }
+
+  /**
+   * @return the signaturePositioning
+   */
+  public SignaturePositioning getSignaturePositioning()
+  {
+    return this.signaturePositioning;
+  }
+
+  /**
+   * @param signaturePositioning
+   *          the signaturePositioning to set
+   */
+  public void setSignaturePositioning(SignaturePositioning signaturePositioning)
+  {
+    this.signaturePositioning = signaturePositioning;
+  }
+
+  /**
+   * @return the output
+   */
+  public DataSink getOutput()
+  {
+    return output;
+  }
+
+  /**
+   * @param output
+   *          the output to set
+   */
+  public void setOutput(DataSink output)
+  {
+    this.output = output;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java b/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java
new file mode 100644
index 0000000..519a9e1
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java
@@ -0,0 +1,49 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign;
+
+import java.security.cert.X509Certificate;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition;
+
+/**
+ * The result of a sign operation.
+ * 
+ * @author wprinz
+ */
+public interface SignResult
+{
+
+  /**
+   * Returns the filled output data sink.
+   * 
+   * @return Returns the filled output data sink.
+   */
+  public DataSink getOutputDocument();
+
+  /**
+   * Returns the certificate of the signer.
+   * 
+   * @return Returns the certificate of the signer.
+   */
+  public X509Certificate getSignerCertificate();
+
+  /**
+   * Returns the position where the signature is finally placed.
+   * 
+   * <p>
+   * This information can be useful for post-processing the document.
+   * </p>
+   * 
+   * <p>
+   * Consult the PDF-AS documentation section Commandline for further
+   * information about positioning.
+   * </p>
+   * 
+   * @return Returns the position where the signature is finally placed. May
+   *         return null if no position information is available.
+   */
+  public SignaturePosition getSignaturePosition();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java
new file mode 100644
index 0000000..8dc6b6c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java
@@ -0,0 +1,52 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos;
+
+/**
+ * Holds the actual, absolute signature position where a signature was placed.
+ * 
+ * <p>
+ * This is usually returned after signing.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface SignaturePosition
+{
+  /**
+   * Returns the page on which the signature was placed.
+   * 
+   * @return Returns the page on which the signature was placed.
+   */
+  public int getPage();
+
+  /**
+   * Returns the x position.
+   * 
+   * @return Returns the x position.
+   */
+  public float getX();
+
+  /**
+   * Returns the y position.
+   * 
+   * @return Returns the y position.
+   */
+  public float getY();
+
+  /**
+   * Returns the width of the signature.
+   * 
+   * @return Returns the width of the signature.
+   */
+  public float getWidth();
+
+  /**
+   * Returns the height of the signature.
+   * 
+   * @return Returns the height of the signature.
+   */
+  public float getHeight();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java
new file mode 100644
index 0000000..b9e2c8a
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java
@@ -0,0 +1,189 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos;
+
+import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AutoAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AutoPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.PageAlgorithm;
+
+/**
+ * Defines how the signature positioning is to be performed.
+ * 
+ * <p>
+ * This positioning allows to select the location where the signature block is
+ * placed in the document.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public class SignaturePositioning
+{
+  /**
+   * The x axis algorithm.
+   * 
+   * <p>
+   * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+   * </p>
+   */
+  protected AxisAlgorithm xAlgorithm = new AutoAxisAlgorithm();
+
+  /**
+   * The y axis algorithm.
+   * 
+   * <p>
+   * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+   * </p>
+   */
+  protected AxisAlgorithm yAlgorithm = new AutoAxisAlgorithm();
+
+  /**
+   * The width algorithm.
+   * 
+   * <p>
+   * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+   * </p>
+   */
+  protected AxisAlgorithm widthAlgorithm = new AutoAxisAlgorithm();
+
+  /**
+   * The page algorithm.
+   * 
+   * <p>
+   * May be {@link AutoPageAlgorithm}, {@link AbsolutePageAlgorithm} or
+   * {@link NewPageAlgorithm}
+   * </p>
+   */
+  protected PageAlgorithm pageAlgorithm = new AutoPageAlgorithm();
+
+  /**
+   * Provides the position of the footline.
+   * 
+   * <p>
+   * Only used if the pageAlgorithm is {@link AutoPageAlgorithm} and the
+   * yAlgorithm is {@link AutoAxisAlgorithm}
+   * </p>
+   */
+  protected float footerLine = 0.0f;
+
+  protected void checkAxisAlgorithm(AxisAlgorithm algorithm)
+  {
+    if (algorithm == null)
+    {
+      throw new IllegalArgumentException("The algorithm must not be null.");
+    }
+    if (!(algorithm instanceof AutoAxisAlgorithm) && !(algorithm instanceof AbsoluteAxisAlgorithm))
+    {
+      throw new IllegalArgumentException("The algorithm must be either Auto or Absolute.");
+    }
+  }
+
+  protected void checkPageAlgorithm(PageAlgorithm algorithm)
+  {
+    if (algorithm == null)
+    {
+      throw new IllegalArgumentException("The algorithm must not be null.");
+    }
+    if (!(algorithm instanceof AutoPageAlgorithm) && !(algorithm instanceof AbsolutePageAlgorithm) && !(algorithm instanceof NewPageAlgorithm))
+    {
+      throw new IllegalArgumentException("The algorithm must be either Auto or Absolute.");
+    }
+
+  }
+
+  /**
+   * @return the xAlgorithm
+   */
+  public AxisAlgorithm getXAlgorithm()
+  {
+    return this.xAlgorithm;
+  }
+
+  /**
+   * @param algorithm
+   *          the xAlgorithm to set
+   */
+  public void setXAlgorithm(AxisAlgorithm algorithm)
+  {
+    checkAxisAlgorithm(algorithm);
+    xAlgorithm = algorithm;
+  }
+
+  /**
+   * @return the yAlgorithm
+   */
+  public AxisAlgorithm getYAlgorithm()
+  {
+    return this.yAlgorithm;
+  }
+
+  /**
+   * @param algorithm
+   *          the yAlgorithm to set
+   */
+  public void setYAlgorithm(AxisAlgorithm algorithm)
+  {
+    checkAxisAlgorithm(algorithm);
+
+    yAlgorithm = algorithm;
+  }
+
+  /**
+   * @return the widthAlgorithm
+   */
+  public AxisAlgorithm getWidthAlgorithm()
+  {
+    return this.widthAlgorithm;
+  }
+
+  /**
+   * @param widthAlgorithm
+   *          the widthAlgorithm to set
+   */
+  public void setWidthAlgorithm(AxisAlgorithm widthAlgorithm)
+  {
+    checkAxisAlgorithm(widthAlgorithm);
+
+    this.widthAlgorithm = widthAlgorithm;
+  }
+
+  /**
+   * @return the pageAlgorithm
+   */
+  public PageAlgorithm getPageAlgorithm()
+  {
+    return this.pageAlgorithm;
+  }
+
+  /**
+   * @param pageAlgorithm
+   *          the pageAlgorithm to set
+   */
+  public void setPageAlgorithm(PageAlgorithm pageAlgorithm)
+  {
+    checkPageAlgorithm(pageAlgorithm);
+    this.pageAlgorithm = pageAlgorithm;
+  }
+
+  /**
+   * @return the footerLine
+   */
+  public float getFooterLine()
+  {
+    return this.footerLine;
+  }
+
+  /**
+   * @param footerLine
+   *          the footerLine to set
+   */
+  public void setFooterLine(float footerLine)
+  {
+    this.footerLine = footerLine;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java
new file mode 100644
index 0000000..234484c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java
@@ -0,0 +1,35 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * An absolute positioned element.
+ * @author wprinz
+ */
+public class AbsoluteAxisAlgorithm extends AxisAlgorithm
+{
+
+  /**
+   * The absolute positioning value on the axis.
+   */
+  protected float absoluteValue = 0.0f;
+  
+  /**
+   * Constructor.
+   * @param absoluteValue The absolute positioning value on the axis.
+   */
+  public AbsoluteAxisAlgorithm (float absoluteValue)
+  {
+    this.absoluteValue = absoluteValue;
+  }
+
+  /**
+   * Returns absolute positioning value on the axis.
+   * @return the absoluteValue Returns absolute positioning value on the axis.
+   */
+  public float getAbsoluteValue()
+  {
+    return this.absoluteValue;
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java
new file mode 100644
index 0000000..4c5459f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * Auto positioning for this element.
+ * 
+ * @author wprinz
+ */
+public class AutoAxisAlgorithm extends AxisAlgorithm
+{
+// empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java
new file mode 100644
index 0000000..a4baac6
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * Determines how a certain position is chosen on the axis (x, y, width).
+ * 
+ * @author wprinz
+ */
+public abstract class AxisAlgorithm
+{
+// base class
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java
new file mode 100644
index 0000000..206aa19
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java
@@ -0,0 +1,37 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * The page is selected absolutely by giving the page number directly.
+ * 
+ * @author wprinz
+ */
+public class AbsolutePageAlgorithm extends PageAlgorithm
+{
+  /**
+   * The page.
+   */
+  protected int page = -1;
+
+  /**
+   * Constructor.
+   * 
+   * @param page
+   *          The page.
+   */
+  public AbsolutePageAlgorithm(int page)
+  {
+    this.page = page;
+  }
+
+  /**
+   * @return the page
+   */
+  public int getPage()
+  {
+    return this.page;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java
new file mode 100644
index 0000000..0070d5e
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java
@@ -0,0 +1,20 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * The page for placing the signature is selected automatically.
+ * 
+ * <p>
+ * The algorithm first tries to place the signature on the free space of the
+ * last page (considering the footer). If there is not enough space on the last
+ * page, a new page is appended and the signature is placed there.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public class AutoPageAlgorithm extends PageAlgorithm
+{
+// empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java
new file mode 100644
index 0000000..2a8f67c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * Places the signature on a new Page.
+ * 
+ * @author wprinz
+ */
+public class NewPageAlgorithm extends PageAlgorithm
+{
+  // empty block
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java
new file mode 100644
index 0000000..9b0fe8a
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * Determines how the page on which the signature is to be placed is selected.
+ * 
+ * @author wprinz
+ */
+public abstract class PageAlgorithm
+{
+  // empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java b/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java
new file mode 100644
index 0000000..df29570
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java
@@ -0,0 +1,31 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+/**
+ * The result of a signature check performed by a verification device.
+ * 
+ * @see VerifyResult
+ * 
+ * @author wprinz
+ */
+public interface SignatureCheck
+{
+  /**
+   * Returns the response code of the check.
+   * 
+   * @return Returns the response code of the check.
+   */
+  public int getCode();
+
+  /**
+   * Returns the textual response message of the check (corresponding to the
+   * code).
+   * 
+   * @return Returns the textual response message of the check (corresponding to
+   *         the code).
+   */
+  public String getMessage();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java
new file mode 100644
index 0000000..dd50d79
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java
@@ -0,0 +1,117 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
+import at.gv.egiz.pdfas.api.commons.Constants;
+
+/**
+ * Parameter object that holds the verify after analysis parameters.
+ * 
+ * @author wprinz
+ */
+public class VerifyAfterAnalysisParameters
+{
+
+  /**
+   * The list of signatures to be verified.
+   */
+  protected AnalyzeResult analyzeResult = null;
+
+  /**
+   * The signature device to perform the actual signature.
+   * 
+   * <p>
+   * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+   * {@link Constants#SIGNATURE_DEVICE_BKU}.
+   * </p>
+   */
+  protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+  /**
+   * Allows to pass a VerificationTime to the signature device.
+   */
+  protected Date verificationTime = null;
+
+  /**
+   * Tells the signature device (e.g. MOA) to return the signature hash input
+   * data (which is the probably transformed signed data).
+   * 
+   * <p>
+   * Note that this forces MOA to return the potentially large signature data to
+   * be returned in the result XML, which may result in very bad performance.
+   * </p>
+   */
+  protected boolean returnHashInputData = false;
+
+  /**
+   * @return the analyzeResult
+   */
+  public AnalyzeResult getAnalyzeResult()
+  {
+    return this.analyzeResult;
+  }
+
+  /**
+   * @param analyzeResult
+   *          the analyzeResult to set
+   */
+  public void setAnalyzeResult(AnalyzeResult analyzeResult)
+  {
+    this.analyzeResult = analyzeResult;
+  }
+
+  /**
+   * @return the signatureDevice
+   */
+  public String getSignatureDevice()
+  {
+    return this.signatureDevice;
+  }
+
+  /**
+   * @param signatureDevice
+   *          the signatureDevice to set
+   */
+  public void setSignatureDevice(String signatureDevice)
+  {
+    this.signatureDevice = signatureDevice;
+  }
+
+  /**
+   * @return the verificationTime
+   */
+  public Date getVerificationTime()
+  {
+    return this.verificationTime;
+  }
+
+  /**
+   * @param verificationTime the verificationTime to set
+   */
+  public void setVerificationTime(Date verificationTime)
+  {
+    this.verificationTime = verificationTime;
+  }
+
+  /**
+   * @return the returnHashInputData
+   */
+  public boolean isReturnHashInputData()
+  {
+    return this.returnHashInputData;
+  }
+
+  /**
+   * @param returnHashInputData
+   *          the returnHashInputData to set
+   */
+  public void setReturnHashInputData(boolean returnHashInputData)
+  {
+    this.returnHashInputData = returnHashInputData;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java
new file mode 100644
index 0000000..fb3b8b8
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java
@@ -0,0 +1,183 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Parameter object that holds the verify parameters.
+ * 
+ * @author wprinz
+ */
+public class VerifyParameters
+{
+  // This would be a perfect point for multiple inheritance in Java.
+  // VerifyParameters extends AnalyzeParameters, VerifyAfterAnalysisParameters
+  // Then a lot of code could be easily reused in the PdfAsObject's check*Parameters methods.
+
+  /**
+   * The document to be verified.
+   */
+  protected DataSource document = null;
+
+  /**
+   * The signature device to perform the actual signature.
+   * 
+   * <p>
+   * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+   * {@link Constants#SIGNATURE_DEVICE_BKU}.
+   * </p>
+   */
+  protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+  /**
+   * The mode of operation how the document is analyzed.
+   * 
+   * <p>
+   * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for
+   * binary signatures only (very fast). Or may be
+   * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi
+   * conservative (optimized) text and binary verification (slow). Or may be
+   * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full
+   * conservative text and binary verification (very slow).
+   * </p>
+   */
+  protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+  /**
+   * The (zero based) index of the signature to verify.
+   * 
+   * <p>
+   * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to
+   * verify all found signatures.
+   * </p>
+   */
+  protected int signatureToVerify = Constants.VERIFY_ALL;
+
+  /**
+   * Allows to pass a VerificationTime to the verification device.
+   * 
+   * <p>
+   * Note that the actual usage of this parameter depends on the verification device.
+   * </p>
+   */
+  protected Date verificationTime = null;
+
+  /**
+   * Tells the signature device (e.g. MOA) to return the signature hash input
+   * data (which is the probably transformed signed data).
+   * 
+   * <p>
+   * Note that this forces MOA to return the potentially large signature data to
+   * be returned in the result XML, which may result in very bad performance.
+   * </p>
+   */
+  protected boolean returnHashInputData = false;
+
+  /**
+   * @return the document
+   */
+  public DataSource getDocument()
+  {
+    return this.document;
+  }
+
+  /**
+   * @param document
+   *          the document to set
+   */
+  public void setDocument(DataSource document)
+  {
+    this.document = document;
+  }
+
+  /**
+   * @return the signatureDevice
+   */
+  public String getSignatureDevice()
+  {
+    return this.signatureDevice;
+  }
+
+  /**
+   * @param signatureDevice
+   *          the signatureDevice to set
+   */
+  public void setSignatureDevice(String signatureDevice)
+  {
+    this.signatureDevice = signatureDevice;
+  }
+
+  /**
+   * @return the verifyMode
+   */
+  public String getVerifyMode()
+  {
+    return this.verifyMode;
+  }
+
+  /**
+   * @param verifyMode
+   *          the verifyMode to set
+   */
+  public void setVerifyMode(String verifyMode)
+  {
+    this.verifyMode = verifyMode;
+  }
+
+  /**
+   * @return the signatureToVerify
+   */
+  public int getSignatureToVerify()
+  {
+    return this.signatureToVerify;
+  }
+
+  /**
+   * @param signatureToVerify
+   *          the signatureToVerify to set
+   */
+  public void setSignatureToVerify(int signatureToVerify)
+  {
+    this.signatureToVerify = signatureToVerify;
+  }
+
+  /**
+   * @return the verificationTime
+   */
+  public Date getVerificationTime()
+  {
+    return this.verificationTime;
+  }
+
+  /**
+   * @param verificationTime
+   *          the verificationTime to set
+   */
+  public void setVerificationTime(Date verificationTime)
+  {
+    this.verificationTime = verificationTime;
+  }
+
+  /**
+   * @return the returnHashInputData
+   */
+  public boolean isReturnHashInputData()
+  {
+    return this.returnHashInputData;
+  }
+
+  /**
+   * @param returnHashInputData
+   *          the returnHashInputData to set
+   */
+  public void setReturnHashInputData(boolean returnHashInputData)
+  {
+    this.returnHashInputData = returnHashInputData;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java
new file mode 100644
index 0000000..be5a88f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java
@@ -0,0 +1,97 @@
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+
+/**
+ * Encapsulates the data of a verification of one signature.
+ * 
+ * @author wprinz
+ */
+public interface VerifyResult extends SignatureInformation
+{
+  /**
+   * Returns the result of the certificate check.
+   * 
+   * @return Returns the result of the certificate check.
+   */
+  public SignatureCheck getCertificateCheck();
+
+  /**
+   * Returns the result of the value (and hash) check.
+   * 
+   * @return Returns the result of the value (and hash) check.
+   */
+  public SignatureCheck getValueCheckCode();
+
+  /**
+   * Returns the result of the manifest check.
+   * 
+   * @return Returns the result of the manifest check.
+   */
+  public SignatureCheck getManifestCheckCode();
+
+  /**
+   * Returns true, if the signer's certificate is a qualified certificate.
+   * 
+   * @return Returns true, if the signer's certificate is a qualified
+   *         certificate.
+   */
+  public boolean isQualifiedCertificate();
+
+  /**
+   * Returns a list of Strings each stating one public property of the
+   * certificate.
+   * 
+   * <p>
+   * Such public properties are certificate extensions each being assigned an
+   * own OID. For example the public property "Verwaltungseigenschaft" has the
+   * OID "1.2.40.0.10.1.1.1".
+   * </p>
+   * 
+   * @return Returns the list of Strings representing the public properties of
+   *         this certificate, if any.
+   */
+  public List getPublicProperties();
+
+  /**
+   * Returns the verification time, which is the time when the signature was
+   * verified.
+   * 
+   * <p>
+   * Note that this is actually the Date passed to the verify methods over
+   * {@link VerifyParameters#setVerificationTime(Date)} or
+   * {@link VerifyAfterAnalysisParameters#setVerificationTime(Date)}. The
+   * signature devices don't respond the actual verification time so there is no
+   * guarantee that the set verification time was actually used as time of
+   * verification. Please consult the device's documentation for more
+   * information.
+   * </p>
+   * 
+   * @return Returns the verification time, which is the time when the signature
+   *         was verified.
+   */
+  public Date getVerificationTime();
+
+  /**
+   * Returns the hash input data as returned by MOA.
+   * 
+   * <p>
+   * This will only return a value other than null if the corresponding
+   * VerifyParameter was set to true.
+   * </p>
+   * <p>
+   * Note that the HashInputData does not necessarily have to be exactly the
+   * same as the signed date return by the
+   * {@link SignatureInformation#getSignedData()} method.
+   * </p>
+   * 
+   * @return Returns the hash input data as returned by MOA.
+   * 
+   * @see SignatureInformation#getSignedData()
+   */
+  public String getHashInputData();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java
new file mode 100644
index 0000000..abda1fe
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java
@@ -0,0 +1,27 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.List;
+
+/**
+ * The result of the verification of a document.
+ * 
+ * <p>
+ * Currently, this is not more than a list of VerifyResult objects, one for each
+ * verified signature. There may be additional items in future PDF-AS versions.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public interface VerifyResults
+{
+  /**
+   * Returns the List of VerifyResult objects, one for each verified signature.
+   * 
+   * @return Returns the List of VerifyResult objects, one for each verified
+   *         signature.
+   */
+  public List getResults();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/commandline/Main.java b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
new file mode 100644
index 0000000..415c1fd
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
@@ -0,0 +1,1071 @@
+/**
+ * <copyright> Copyright (c) 2006 by Know-Center, Graz, Austria </copyright>
+ * 
+ * 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.gv.egiz.pdfas.commandline;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.PropertyConfigurator;
+
+import at.gv.egiz.pdfas.PdfAsFactory;
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.api.verify.VerifyResults;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.ErrorCodeHelper;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.framework.config.SettingsHelper;
+import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
+import at.gv.egiz.pdfas.io.FileBasedDataSink;
+import at.gv.egiz.pdfas.io.FileBasedDataSource;
+import at.gv.egiz.pdfas.io.StringTextBasedDataSource;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
+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.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+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.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.web.servlets.VerifyServlet;
+
+/**
+ * The main program entry point of the commandline tool.
+ * 
+ * <p>
+ * The commandline uses the PDF-AS API.
+ * </p>
+ * 
+ * @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 log.
+   */
+  private static final Log logger_ = LogFactory.getLog(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");
+
+    // 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;
+
+    try
+    {
+
+      // 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;
+      }
+
+      if (mode.equals(VALUE_MODE_SIGN) && output == null)
+      {
+        output = generateOutputFileNameFromInput(input, signature_mode);
+      }
+
+      carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string);
+
+    }
+    catch (PdfAsException e)
+    {
+      printPresentableException(e);
+
+      if (output != null)
+      {
+        logger_.debug("Deleting output file on error.");
+        File oFile = new File(output);
+        boolean deleted = oFile.delete();
+        if (!deleted)
+        {
+          logger_.error("Couldn't delete output file " + output);
+        }
+      }
+    }
+    finally
+    {
+      SettingsReader.clearTemporaryDirectory();
+    }
+  }
+
+  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 PdfAsException
+  {
+    // 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);
+    // }
+
+    PrintWriter messageOutput = new PrintWriter(System.out);
+
+    if (mode.equals(VALUE_MODE_SIGN))
+    {
+      carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput);
+    }
+    else
+    {
+      carryOutVerify(input, connector, verify_which, messageOutput);
+    }
+    messageOutput.flush();
+  }
+
+  public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output,
+      PrintWriter messageOutput) throws PdfAsException
+  {
+    messageOutput.println("Signing...");
+
+    // for performance measurement
+    long startTime = 0;
+    long fileSize = 0;
+    if (logger_.isInfoEnabled())
+    {
+      startTime = System.currentTimeMillis();
+    }
+
+    DataSource dataSource = null;
+    try
+    {
+      File file = new File(input);
+      dataSource = new FileBasedDataSource(file, "application/pdf");
+      if (logger_.isDebugEnabled())
+      {
+        fileSize = file.length();
+      }
+    }
+    catch (IOException e)
+    {
+      throw new PDFDocumentException(201, e);
+    }
+
+    DataSink dataSink = null;
+    try
+    {
+      File outputFile = new File(output);
+
+      dataSink = new FileBasedDataSink(outputFile);
+    }
+    catch (IOException e)
+    {
+      throw new PDFDocumentException(ErrorCode.CANNOT_WRITE_PDF, e);
+    }
+
+    processSign(dataSource, connector, signature_mode, signature_type, pos_string, dataSink);
+
+    // for performance measurement
+    if (logger_.isInfoEnabled())
+    {
+      long endTime = System.currentTimeMillis();
+      String toReport = "SIGN;" + signature_mode + ";" + input + ";" + fileSize + ";" + (endTime - startTime);
+      logger_.info(toReport);
+    }
+
+    messageOutput.println("Signing was successful.");
+  }
+
+  public static void carryOutVerify(String input, String connector, int verify_which, PrintWriter messageOutput) throws PdfAsException
+  {
+    messageOutput.println("Verifying...");
+
+    // for performance measurement
+    long startTime = 0;
+    long fileSize = 0;
+    if (logger_.isInfoEnabled())
+    {
+      startTime = System.currentTimeMillis();
+    }
+
+    DataSource dataSource = null;
+    try
+    {
+      File file = new File(input);
+      if (logger_.isDebugEnabled())
+      {
+        fileSize = file.length();
+      }
+      String extension = VerifyServlet.extractExtension(input);
+      if (extension != null && extension.equals("txt"))
+      {
+        try
+        {
+          FileInputStream fis = new FileInputStream(file);
+          byte[] input_bytes = new byte[(int) file.length()];
+          fis.read(input_bytes);
+          fis.close();
+
+          String text = new String(input_bytes, "UTF-8");
+          dataSource = new StringTextBasedDataSource(text);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+          throw new RuntimeException("Very strange: UTF-8 character encoding not supported.", e);
+        }
+      }
+      else
+      {
+        dataSource = new FileBasedDataSource(file, "application/pdf");
+      }
+    }
+    catch (IOException e)
+    {
+      throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+    }
+
+    VerifyResults results = processVerify(dataSource, connector, verify_which);
+
+    messageOutput.println("Verification results:");
+    formatVerifyResults(results, messageOutput);
+
+    // for performance measurement
+    if (logger_.isInfoEnabled())
+    {
+      long endTime = System.currentTimeMillis();
+      String toReport = "VERIFY;" + input + ";" + fileSize + ";" + (endTime - startTime) + ";" + debugVerifyResults(results);
+      logger_.info(toReport);
+    }
+
+  }
+
+  public static void processSign(DataSource dataSource, String connector, String signature_mode, String signature_type, String pos_string, DataSink dataSink) throws PdfAsException
+  {
+    // FIXME implement this
+    // TODO this will change soon due to the document-cleaning change request.
+    //PdfAS.applyStrictMode(pdfDataSource);
+
+    TablePos pos = null;
+    if (pos_string != null)
+    {
+      try
+      {
+        pos = PdfAS.parsePositionFromPosString(pos_string);
+      }
+      catch (PDFDocumentException e)
+      {
+        printUnrecognizedValue(PARAMETER_POS, pos_string);
+        return;
+
+      }
+    }
+    SignaturePositioning posi = null;
+    if (pos != null)
+    {
+      posi = new SignaturePositioning();
+      if (!pos.isXauto())
+      {
+        posi.setXAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosX()));
+      }
+      if (!pos.isYauto())
+      {
+        posi.setYAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosY()));
+      }
+      if (!pos.isWauto())
+      {
+        posi.setWidthAlgorithm(new AbsoluteAxisAlgorithm(pos.getWidth()));
+      }
+      if (pos.isNewPage())
+      {
+        posi.setPageAlgorithm(new NewPageAlgorithm());
+      }
+      if (!pos.isPauto())
+      {
+        posi.setPageAlgorithm(new AbsolutePageAlgorithm(pos.getPage()));
+      }
+      posi.setFooterLine(pos.getFooterLine());
+    }
+
+    PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH));
+
+    SignParameters sp = new SignParameters();
+    sp.setDocument(dataSource);
+    sp.setOutput(dataSink);
+    sp.setSignatureType(signature_mode); // TODO detached signaturen!
+    sp.setSignatureDevice(connector);
+    sp.setSignatureProfileId(signature_type);
+    sp.setSignaturePositioning(posi);
+    pdfAs.sign(sp);
+
+  }
+
+  public static VerifyResults processVerify(DataSource dataSource, String connector, int verify_which) throws PdfAsException
+  {
+    String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+    VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
+    if (parameters.extractBinarySignaturesOnly())
+    {
+      verifyMode = Constants.VERIFY_MODE_BINARY_ONLY;
+    }
+    else
+    {
+      if (parameters.assumeOnlySignatureUpdateBlocks())
+      {
+        verifyMode = Constants.VERIFY_MODE_SEMI_CONSERVATIVE;
+      }
+      else
+      {
+        verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+      }
+    }
+
+    PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH));
+
+    VerifyParameters vp = new VerifyParameters();
+    vp.setDocument(dataSource);
+    vp.setVerifyMode(verifyMode);
+    vp.setSignatureDevice(connector);
+    vp.setReturnHashInputData(false);
+    vp.setVerificationTime(null);
+    vp.setSignatureToVerify(verify_which);
+    VerifyResults vrs = pdfAs.verify(vp);
+
+    return vrs;
+  }
+
+  protected static String generateOutputFileNameFromInput(String input, String sig_mode)
+  {
+    String output = input + "_out";
+    if (sig_mode.startsWith("detached"))
+    {
+      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 printPresentableException(final PdfAsException e)
+  {
+    if (e.getErrorCode() == ErrorCode.PLACEHOLDER_EXCEPTION)
+    {
+      PlaceholderException phe = null;
+      if (e instanceof PlaceholderException)
+      {
+        phe = (PlaceholderException) e;
+      }
+      else
+      {
+        phe = (PlaceholderException) e.getCause();
+      }
+
+      System.err.println("Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz. ");
+    }
+
+    System.err.println("Fehler " + e.getErrorCode() + ": " + ErrorCodeHelper.getMessageForErrorCode(e.getErrorCode()));
+
+    if (e instanceof ExternalErrorException)
+    {
+      ExternalErrorException eee = (ExternalErrorException) e;
+      System.err.println("Externer Fehlergrund: " + eee.getExternalErrorCode() + ": " + eee.getExternalErrorMessage());
+    }
+
+    logger_.error(e);
+  }
+
+  /**
+   * 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] <input file> [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");
+    // @iaik: why is this commented out?
+    //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 + " <user_name> ... [optional] the user name");
+    writer.println("    " + PARAMETER_USER_PASSWORD + " <password> ... [optional] the user password");
+
+    writer.println("    " + PARAMETER_POS + " <position> ... [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 + " <number> ... [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(VerifyResults results, PrintWriter writer) throws SettingNotFoundException
+  {
+    Iterator it = results.getResults().iterator();
+    while (it.hasNext())
+    {
+      VerifyResult result = (VerifyResult) it.next();
+      formatVerifyResult(result, writer);
+
+      if (it.hasNext())
+      {
+        writer.println();
+      }
+    }
+  }
+
+  /**
+   * Formats the verification results for debugging. Returns 0 if no error
+   * occurs or the sum of all error-codes.
+   * 
+   * @param results
+   * 
+   * @param writer
+   *          The output sink to write the formatted text to.
+   * @throws SettingNotFoundException
+   *           Forwarded exception.
+   */
+  protected static int debugVerifyResults(VerifyResults results) throws SettingNotFoundException
+  {
+    int toreturn = 0;
+    Iterator it = results.getResults().iterator();
+    while (it.hasNext())
+    {
+      VerifyResult result = (VerifyResult) it.next();
+
+      toreturn += result.getValueCheckCode().getCode();
+    }
+    return toreturn;
+  }
+
+  public static void formatVerifyResult(VerifyResult result, PrintWriter writer) throws SettingNotFoundException
+  {
+
+    writer.println("  Zertifikat:");
+    writer.println("    Signator:     " + result.getSignerCertificate().getSubjectDN().getName());
+    writer.println("    Aussteller:   " + result.getSignerCertificate().getIssuerDN().getName());
+    writer.println("    Seriennummer: " + result.getSignerCertificate().getSerialNumber());
+    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.getCertificateCheck().getCode() + " - " + result.getCertificateCheck().getMessage());
+    writer.println("  Signatur-Check:");
+    writer.println("    " + result.getValueCheckCode().getCode() + " - " + result.getValueCheckCode().getMessage());
+    writer.println("  Manifest-Check:");
+    writer.println("    " + result.getManifestCheckCode().getCode() + " - " + result.getManifestCheckCode().getMessage());
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
index b42c8ed..99d692e 100644
--- a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
+++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
@@ -33,34 +33,34 @@ public class ConnectorFactory
    
 
   
-  public static Connector createConnector (String connectorId, String profile, String locRef) throws ConnectorFactoryException, ConnectorException
+  public static Connector createConnector (String connectorId, ConnectorParameters connectorParameters) throws ConnectorFactoryException, ConnectorException
   {
     if (connectorId.equals(DETACHED_MULTIPART_BKU_CONNECTOR))
     {
-      return new MultipartDetachedBKUConnector(profile);
+      return new MultipartDetachedBKUConnector(connectorParameters);
     }
     
     if (connectorId.equals(ENVELOPING_BASE64_BKU_CONNECTOR))
     {
-      return new EnvelopedBase64BKUConnector(profile);
+      return new EnvelopedBase64BKUConnector(connectorParameters.getProfileId());
     }
 
     if (connectorId.equals(OLD_ENVELOPING_BASE64_BKU_CONNECTOR))
     {
-      return new OldEnvelopingBase64BKUConnector(profile);
+      return new OldEnvelopingBase64BKUConnector(connectorParameters.getProfileId());
     }
 
     if (connectorId.equals(DETACHED_LOCREF_MOA_CONNECTOR))
     {
 //    	TODO Hier wird der neue Connector verwendet
 //      return new DetachedLocRefMOAConnector(profile, locRef);
-      return new MOASoapWithAttachmentConnector(profile);
+      return new MOASoapWithAttachmentConnector(connectorParameters);
     }
     
     if (connectorId.equals(ENVELOPING_BASE64_MOA_CONNECTOR))
     {
 //    	TODO Hier wird NICHT der neue Connector verwendet
-      return new EnvelopingBase64MOAConnector(profile);
+      return new EnvelopingBase64MOAConnector(connectorParameters.getProfileId());
 //      return new MOASoapWithAttachmentConnector(profile);
     }
 
diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java
new file mode 100644
index 0000000..618624d
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java
@@ -0,0 +1,85 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.framework;
+
+import java.util.Date;
+
+/**
+ * Parameters passed to the constructor of the Connector.
+ * 
+ * <p>
+ * Each Connector must have a constructor accepting this parameter class as an
+ * argument.
+ * </p>
+ * 
+ * @author wprinz
+ */
+public class ConnectorParameters
+{
+  /**
+   * The profile Id to get the connector parameters from.
+   * 
+   * <p>
+   * The there are no explicit parameters for the connector in the profile, the
+   * default parameters are used.
+   * </p>
+   */
+  protected String profileId = null;
+
+  /**
+   * Tells, if the connector should ask the device to return the hash input
+   * data.
+   * 
+   * <p>
+   * Note that not all connectors support to return the hash input data - so
+   * there is no guarantee that the hash value will actually be returned.
+   * </p>
+   */
+  protected boolean returnHashInputData = false;
+
+  /**
+   * Allows to specify an explicit time of verification.
+   * 
+   * <p>
+   * If null, the device's default behaviour determines the time of
+   * verification, which is usually the current time.
+   * </p>
+   * <p>
+   * The time of verification usually influences the certificate check. E.g. the
+   * certificate may not be valid at the time of verification.
+   * </p>
+   */
+  protected Date verificationTime = null;
+
+  public String getProfileId()
+  {
+    return this.profileId;
+  }
+
+  public void setProfileId(String profileId)
+  {
+    this.profileId = profileId;
+  }
+
+  public boolean isReturnHashInputData()
+  {
+    return this.returnHashInputData;
+  }
+
+  public void setReturnHashInputData(boolean returnHashInputData)
+  {
+    this.returnHashInputData = returnHashInputData;
+  }
+
+  public Date getVerificationTime()
+  {
+    return this.verificationTime;
+  }
+
+  public void setVerificationTime(Date verificationTime)
+  {
+    this.verificationTime = verificationTime;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java b/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java
index da81e87..9abf509 100644
--- a/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java
+++ b/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java
@@ -3,6 +3,7 @@
  */
 package at.gv.egiz.pdfas.framework.signator;
 
+import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos;
 import at.knowcenter.wag.egov.egiz.sig.SignatureData;
 import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 
@@ -40,4 +41,23 @@ public interface SignatorInformation
    *          The SignSignatureObject.
    */
   public void setSignSignatureObject(SignSignatureObject signSignatureObject);
+
+  /**
+   * Returns the SignSignatureObject.
+   * 
+   * <p>
+   * After signation, this is used by the framework/API to get additional
+   * information about the signature.
+   * </p>
+   * 
+   * @return Returns the SignSignatureObject.
+   */
+  public SignSignatureObject getSignSignatureObject();
+
+  /**
+   * Returns the position where the signature table was actually placed.
+   * 
+   * @return Returns the position where the signature table was actually placed.
+   */
+  public ActualTablePos getActualTablePos();
 }
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java b/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java
new file mode 100644
index 0000000..467113f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java
@@ -0,0 +1,213 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+
+/**
+ * Contains check methods frequently used by the {@link PdfAsObject} to check
+ * input parameters.
+ * 
+ * @author wprinz
+ * 
+ */
+public final class CheckHelper
+{
+  /**
+   * The log.
+   */
+  private static Log log = LogFactory.getLog(CheckHelper.class);
+
+  /**
+   * Hidden default constructor.
+   */
+  private CheckHelper()
+  {
+    // empty block
+  }
+
+  /**
+   * Checks the SignParameters for integrity.
+   * 
+   * @param sp
+   *          The {@link SignParameters}
+   */
+  public static void checkSignParameters(SignParameters sp)
+  {
+    if (sp == null)
+    {
+      throw new IllegalArgumentException("The signParameters must not be null.");
+    }
+
+    checkDocument(sp.getDocument());
+    if (sp.getOutput() == null)
+    {
+      throw new IllegalArgumentException("The output DataSink must not be null.");
+    }
+    checkSignatureType(sp.getSignatureType());
+    checkSignatureDevice(sp.getSignatureDevice());
+    if (sp.getSignatureProfileId() != null)
+    {
+      checkProfileId(sp.getSignatureProfileId());
+    }
+    if (sp.getSignaturePositioning() != null)
+    {
+      checkSignaturePositioning(sp.getSignaturePositioning());
+    }
+  }
+
+  /**
+   * Checks the VerifyParameters for integrity.
+   * 
+   * @param vp
+   *          The {@link VerifyParameters}
+   */
+  public static void checkVerifyParameters(VerifyParameters vp)
+  {
+    if (vp == null)
+    {
+      throw new IllegalArgumentException("The verifyParameters must not be null.");
+    }
+
+    checkDocument(vp.getDocument());
+    checkVerifyMode(vp.getVerifyMode());
+    checkSignatureDevice(vp.getSignatureDevice());
+    if (vp.getSignatureToVerify() < Constants.VERIFY_ALL)
+    {
+      throw new IllegalArgumentException("The signatureToVerify parameter is incorrect. " + vp.getSignatureToVerify());
+    }
+  }
+
+  /**
+   * Checks the AnalyzeParameters for integrity.
+   * 
+   * @param ap
+   *          The {@link AnalyzeParameters}
+   */
+  public static void checkAnalyzeParameters(AnalyzeParameters ap)
+  {
+    if (ap == null)
+    {
+      throw new IllegalArgumentException("The analyzeParameters must not be null.");
+    }
+
+    checkDocument(ap.getDocument());
+    checkVerifyMode(ap.getVerifyMode());
+  }
+
+  /**
+   * Checks the VerifyAfterAnalysisParameters for integrity.
+   * 
+   * @param vaap
+   *          The {@link VerifyAfterAnalysisParameters}
+   */
+  public static void checkVerifyAfterAnalysisParameters(VerifyAfterAnalysisParameters vaap)
+  {
+    if (vaap == null)
+    {
+      throw new IllegalArgumentException("The analyzeParameters must not be null.");
+    }
+
+    if (vaap.getAnalyzeResult() == null)
+    {
+      throw new IllegalArgumentException("The analyzeResult must not be null.");
+    }
+    checkSignatureDevice(vaap.getSignatureDevice());
+  }
+
+  protected static void checkDocument(DataSource document)
+  {
+    if (document == null)
+    {
+      throw new IllegalArgumentException("The document DataSource must not be null.");
+    }
+  }
+
+  protected static void checkSignatureType(String signatureType)
+  {
+    if (signatureType == null)
+    {
+      throw new IllegalArgumentException("The signatureType must not be null.");
+    }
+    if (!(signatureType.equals(Constants.SIGNATURE_TYPE_BINARY) || signatureType.equals(Constants.SIGNATURE_TYPE_TEXTUAL) || signatureType.equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL)))
+    {
+      throw new IllegalArgumentException("The signatureType must be one of the Constants.SIGNATURE_TYPE_* constants. " + signatureType);
+    }
+  }
+
+  protected static void checkProfileId(String profileId)
+  {
+    if (profileId == null)
+    {
+      throw new IllegalArgumentException("The profileId must not be null.");
+    }
+    try
+    {
+      if (!SignatureTypes.getInstance().getSignatureTypes().contains(profileId))
+      {
+        throw new IllegalArgumentException("The profileId must be defined in the configuration file. " + profileId);
+      }
+    }
+    catch (SignatureTypesException e)
+    {
+      String msg = "Error while checking the profileId parameter - cannot get list of valid profiles. " + profileId;
+      log.error(msg, e);
+      throw new IllegalArgumentException(msg);
+    }
+  }
+
+  protected static void checkSignaturePositioning(SignaturePositioning signaturePositioning)
+  {
+    if (signaturePositioning == null)
+    {
+      throw new IllegalArgumentException("The signaturePosition must not be null.");
+    }
+    try
+    {
+      PosHelper.formTablePos(signaturePositioning);
+    }
+    catch (PDFDocumentException e)
+    {
+      String msg = "The signaturePosition string is not valid. " + signaturePositioning;
+      log.error(msg, e);
+      throw new IllegalArgumentException(msg);
+    }
+  }
+
+  protected static void checkVerifyMode(String verifyMode)
+  {
+    if (verifyMode == null)
+    {
+      throw new IllegalArgumentException("The verifyMode must not be null.");
+    }
+    if (!(verifyMode.equals(Constants.VERIFY_MODE_BINARY_ONLY) || verifyMode.equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE) || verifyMode.equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE)))
+    {
+      throw new IllegalArgumentException("The verifyMode must be one of the Constants.VERIFY_MODE_* constants. " + verifyMode);
+    }
+  }
+
+  protected static void checkSignatureDevice(String signatureDevice)
+  {
+    if (signatureDevice == null)
+    {
+      throw new IllegalArgumentException("The signatureDevice must not be null.");
+    }
+    if (!(signatureDevice.equals(Constants.SIGNATURE_DEVICE_BKU) || signatureDevice.equals(Constants.SIGNATURE_DEVICE_MOA)))
+    {
+      throw new IllegalArgumentException("The signatureDevice must be one of the Constants.SIGNATURE_DEVICE_* constants. " + signatureDevice);
+    }
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java b/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
new file mode 100644
index 0000000..a343de8
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
@@ -0,0 +1,317 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
+import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.commons.SignatureProfile;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.api.verify.VerifyResults;
+import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.config.SettingsHelper;
+import at.gv.egiz.pdfas.framework.input.ExtractionStage;
+import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
+import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
+import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl;
+import at.gv.egiz.pdfas.impl.api.commons.DataSinkAdapter;
+import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter;
+import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter;
+import at.gv.egiz.pdfas.impl.api.commons.SignatureProfileImpl;
+import at.gv.egiz.pdfas.impl.api.commons.TextDataSourceAdapter;
+import at.gv.egiz.pdfas.impl.api.sign.ActualSignaturePositionAdapter;
+import at.gv.egiz.pdfas.impl.api.sign.SignResultImpl;
+import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter;
+import at.gv.egiz.pdfas.impl.api.verify.VerifyResultsImpl;
+import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+
+/**
+ * Implementation of the {@link PdfAs} interface.
+ * 
+ * @author wprinz
+ */
+public class PdfAsObject implements PdfAs
+{
+  /**
+   * The work directory.
+   */
+  protected File workDirectory = null;
+
+  /**
+   * This constructor is for internal use only - use
+   * {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
+   * 
+   * @param workDirectory
+   *          The work directory.
+   * @throws PdfAsException
+   *           Thrown, if the configuration cannot be processed.
+   */
+  public PdfAsObject(File workDirectory) throws PdfAsException
+  {
+    if (workDirectory == null)
+    {
+      throw new IllegalArgumentException("The work directory must not be null.");
+    }
+    if (!workDirectory.isDirectory())
+    {
+      throw new IllegalArgumentException("The work directory does not exist or is not a directory. " + workDirectory.getPath());
+    }
+
+    this.workDirectory = workDirectory;
+
+    SettingsReader.initialize(workDirectory.getPath());
+    reloadConfig();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig()
+   */
+  public void reloadConfig() throws PdfAsException
+  {
+    SettingsReader.createInstance();
+    SignatureTypes.createInstance();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#getProfileInformation()
+   */
+  public List getProfileInformation() throws PdfAsException
+  {
+    final String MOA_SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier";
+
+    SettingsReader settings = SettingsReader.getInstance();
+    final String defaultMoaKeyIdentifiert = settings.getSetting(MOA_SIGN_KEY_IDENTIFIER_KEY, null);
+
+    SignatureTypes types = SignatureTypes.getInstance();
+    List profiles = types.getSignatureTypeDefinitions();
+
+    List profileInformation = new ArrayList(profiles.size());
+
+    Iterator it = profiles.iterator();
+    while (it.hasNext())
+    {
+      SignatureTypeDefinition profile = (SignatureTypeDefinition) it.next();
+
+      final String profileId = profile.getType();
+      final String moaKeyIdentifier = settings.getSetting("sig_obj." + profileId + "." + MOA_SIGN_KEY_IDENTIFIER_KEY, defaultMoaKeyIdentifiert);
+
+      SignatureProfile signatureProfile = new SignatureProfileImpl(profileId, moaKeyIdentifier);
+      profileInformation.add(signatureProfile);
+    }
+
+    return profileInformation;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters)
+   */
+  public SignResult sign(SignParameters signParameters) throws PdfAsException
+  {
+    CheckHelper.checkSignParameters(signParameters);
+
+    PdfASID signatorId = null;
+    if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_BINARY))
+    {
+      signatorId = SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID;
+    }
+    if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_TEXTUAL))
+    {
+      signatorId = SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID;
+    }
+    if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL))
+    {
+      signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
+    }
+
+    TablePos pos = PosHelper.formTablePos(signParameters.getSignaturePositioning());
+
+    String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(signParameters.getSignatureDevice());
+
+    SignatorInformation si = PdfAS
+        .signCommandline(new PdfDataSourceAdapter(signParameters.getDocument()), new DataSinkAdapter(signParameters.getOutput()), signatorId, connectorId, signParameters.getSignatureProfileId(), pos);
+
+    return new SignResultImpl(signParameters.getOutput(), si.getSignSignatureObject().getX509Certificate(), new ActualSignaturePositionAdapter(si.getActualTablePos()));
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters)
+   */
+  public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException
+  {
+    CheckHelper.checkVerifyParameters(verifyParameters);
+
+    AnalyzeParameters ap = new AnalyzeParameters();
+    fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters);
+    AnalyzeResult analyzeResult = analyze(ap);
+
+    if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL)
+    {
+      if (verifyParameters.getSignatureToVerify() >= analyzeResult.getSignatures().size())
+      {
+        throw new SignatureException(312, "The selected signature to be verified doesn't exist. " + verifyParameters.getSignatureToVerify());
+      }
+
+      Object stv = analyzeResult.getSignatures().get(verifyParameters.getSignatureToVerify());
+      List selectedSignature = new ArrayList(1);
+      selectedSignature.add(stv);
+      analyzeResult = new AnalyzeResultImpl(selectedSignature);
+    }
+
+    VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
+    vaap.setAnalyzeResult(analyzeResult);
+    fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters);
+    return verify(vaap);
+  }
+ 
+
+  /**
+   * Copies all adequate parameters from the {@link VerifyParameters} to the
+   * {@link AnalyzeParameters}.
+   * 
+   * @param ap
+   *          The {@link AnalyzeParameters}.
+   * @param vp
+   *          The {@link VerifyParameters}.
+   */
+  protected void fillAnalyzeParametersWithVerifyParameters(AnalyzeParameters ap, VerifyParameters vp)
+  {
+    ap.setDocument(vp.getDocument());
+    ap.setVerifyMode(vp.getVerifyMode());
+  }
+
+  /**
+   * Copies all adequate parameters from the {@link VerifyParameters} to the
+   * {@link VerifyAfterAnalysisParameters}.
+   * 
+   * @param vaap
+   *          The {@link VerifyAfterAnalysisParameters}.
+   * @param vp
+   *          The {@link VerifyParameters}.
+   */
+  protected void fillVerifyAfterAnalysisParametersWithVerifyParameters(VerifyAfterAnalysisParameters vaap, VerifyParameters vp)
+  {
+    vaap.setSignatureDevice(vp.getSignatureDevice());
+    vaap.setVerificationTime(vp.getVerificationTime());
+    vaap.setReturnHashInputData(vp.isReturnHashInputData());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters)
+   */
+  public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException
+  {
+    CheckHelper.checkAnalyzeParameters(analyzeParameters);
+
+    VerificationFilterParameters parametersConfig = SettingsHelper.readVerificationFilterParametersFromSettings();
+    boolean binaryOnly = parametersConfig.extractBinarySignaturesOnly();
+    if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_BINARY_ONLY))
+    {
+      binaryOnly = true;
+    }
+    boolean assumeOnlySB = parametersConfig.assumeOnlySignatureUpdateBlocks();
+    if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE))
+    {
+      assumeOnlySB = true;
+    }
+    if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE))
+    {
+      assumeOnlySB = false;
+    }
+    VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures());
+    
+    at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null;
+    if (analyzeParameters.getDocument().getMimeType().equals("application/pdf"))
+    {
+      inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument());
+    }
+    else
+    {
+      try
+      {
+        inputDataSource = new TextDataSourceAdapter(analyzeParameters.getDocument());
+      }
+      catch (UnsupportedEncodingException e)
+      {
+        throw new PresentableException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "The characterEncoding is not supported." + analyzeParameters.getDocument().getCharacterEncoding(), e);
+      }
+    }
+    assert inputDataSource != null;
+    
+    ExtractionStage es = new ExtractionStage();
+    List signature_holders = es.extractSignatureHolders(inputDataSource, parameters);
+
+    List sigInfs = new ArrayList(signature_holders.size());
+    Iterator it = signature_holders.iterator();
+    while (it.hasNext())
+    {
+      SignatureHolder sh = (SignatureHolder)it.next();
+      SignatureInformation si = new SignatureInformationAdapter(sh);
+      sigInfs.add(si);
+    }
+    
+    return new AnalyzeResultImpl(sigInfs);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters)
+   */
+  public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException
+  {
+    CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters);
+
+    List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures();
+    List signature_holders = new ArrayList(signatures.size());
+    Iterator it = signatures.iterator();
+    while (it.hasNext())
+    {
+      SignatureInformation si = (SignatureInformation) it.next();
+      SignatureHolder sh = (SignatureHolder) si.getInternalSignatureInformation();
+      signature_holders.add(sh);
+    }
+    assert signature_holders.size() == signatures.size();
+    
+    List results = PdfAS.verifySignatureHolders(signature_holders, verifyAfterAnalysisParameters.getSignatureDevice(), verifyAfterAnalysisParameters.isReturnHashInputData(), verifyAfterAnalysisParameters.getVerificationTime());
+    
+    List vrs = new ArrayList(results.size());
+    
+    assert signature_holders.size() == results.size() : "Not all signatures were verified.";
+
+    for (int i = 0; i < signature_holders.size(); i++)
+    {
+      SignatureResponse response = (SignatureResponse) results.get(i);
+      SignatureHolder holder = (SignatureHolder) signature_holders.get(i);
+      
+      VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterAnalysisParameters.getVerificationTime());
+      vrs.add(vr);
+    }
+
+    return new VerifyResultsImpl(vrs);
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java b/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java
new file mode 100644
index 0000000..14f081f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java
@@ -0,0 +1,79 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api;
+
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AutoAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AutoPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.PageAlgorithm;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+
+/**
+ * @author wprinz
+ * 
+ */
+public final class PosHelper
+{
+  /**
+   * Hidden default constructor.
+   */
+  private PosHelper()
+  {
+    // empty block
+  }
+
+  public static TablePos formTablePos(SignaturePositioning signaturePositioning) throws PDFDocumentException
+  {
+    if (signaturePositioning == null)
+    {
+      return null;
+    }
+
+    String positioningString = formPositioningString(signaturePositioning);
+    TablePos pos = PdfAS.parsePositionFromPosString(positioningString);
+
+    return pos;
+  }
+
+  protected static String formPositioningString(SignaturePositioning sp)
+  {
+    String x_algo = formAxisAlgoString(sp.getXAlgorithm());
+    String y_algo = formAxisAlgoString(sp.getYAlgorithm());
+    String w_algo = formAxisAlgoString(sp.getWidthAlgorithm());
+    String p_algo = formPageAlgoString(sp.getPageAlgorithm());
+    String positioning = "x:" + x_algo + ";y:" + y_algo + ";w:" + w_algo + ";p:" + p_algo + ";f:" + sp.getFooterLine();
+    return positioning;
+  }
+
+  protected static String formAxisAlgoString(AxisAlgorithm algorithm)
+  {
+    if (algorithm instanceof AutoAxisAlgorithm)
+    {
+      return "auto";
+    }
+    AbsoluteAxisAlgorithm aaa = (AbsoluteAxisAlgorithm) algorithm;
+    return Float.toString(aaa.getAbsoluteValue());
+  }
+
+  protected static String formPageAlgoString(PageAlgorithm algorithm)
+  {
+    if (algorithm instanceof AutoPageAlgorithm)
+    {
+      return "auto";
+    }
+    if (algorithm instanceof NewPageAlgorithm)
+    {
+      return "new";
+    }
+    AbsolutePageAlgorithm apa = (AbsolutePageAlgorithm) algorithm;
+    return Integer.toString(apa.getPage());
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java
new file mode 100644
index 0000000..87a14f0
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java
@@ -0,0 +1,47 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.analyze;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+
+/**
+ * Holds the result of an analyzation.
+ * 
+ * @author wprinz
+ */
+public class AnalyzeResultImpl implements AnalyzeResult
+{
+  /**
+   * The found signatures.
+   */
+  protected List signatures = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param signatures
+   *          The found signatures.
+   */
+  public AnalyzeResultImpl(List signatures)
+  {
+    if (signatures == null)
+    {
+      throw new IllegalArgumentException("The list of found signatures must not be null.");
+    }
+
+    this.signatures = signatures;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.analyze.AnalyzeResult#getSignatures()
+   */
+  public List getSignatures() throws PdfAsException
+  {
+    return this.signatures;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
new file mode 100644
index 0000000..5744a21
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
@@ -0,0 +1,83 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+
+/**
+ * Adapter that converts an API DataSink to a framework DataSink.
+ * 
+ * @author wprinz
+ */
+public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSink
+{
+  /**
+   * The API DataSink to be adapted to a framework DataSink.
+   */
+  protected at.gv.egiz.pdfas.api.io.DataSink apiDataSink = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param apiDataSink
+   *          The API DataSink to be adapted to a framework DataSink.
+   */
+  public DataSinkAdapter(DataSink apiDataSink)
+  {
+    this.apiDataSink = apiDataSink;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType)
+  {
+    try
+    {
+      return this.apiDataSink.createOutputStream(mimeType);
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String,
+   *      java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType, String characterEncoding)
+  {
+    try
+    {
+      return this.apiDataSink.createOutputStream(mimeType, characterEncoding);
+    }
+    catch (IOException e)
+    {
+      e.printStackTrace();
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.output.DataSink#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.apiDataSink.getCharacterEncoding();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.output.DataSink#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.apiDataSink.getMimeType();
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java
new file mode 100644
index 0000000..9e5495c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java
@@ -0,0 +1,85 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import java.io.InputStream;
+
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.input.TextDataSource;
+
+/**
+ * Adapter that converts a framework DataSource to an API PdfDataSource.
+ * 
+ * @author wprinz
+ */
+public class DataSourceApiAdapter implements at.gv.egiz.pdfas.api.io.DataSource
+{
+  /**
+   * The framework DataSource to be adapted to an API DataSource.
+   */
+  protected at.gv.egiz.pdfas.framework.input.DataSource frameworkDataSource = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param frameworkDataSource
+   *          The framework DataSource to be adapted to an API DataSource.
+   */
+  public DataSourceApiAdapter(at.gv.egiz.pdfas.framework.input.DataSource frameworkDataSource)
+  {
+    this.frameworkDataSource = frameworkDataSource;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return this.frameworkDataSource.createInputStream();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    return this.frameworkDataSource.getAsByteArray();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return this.frameworkDataSource.getLength();
+  }
+
+  public String getCharacterEncoding()
+  {
+    if (this.frameworkDataSource instanceof PdfDataSource)
+    {
+      return null;
+    }
+    if (this.frameworkDataSource instanceof TextDataSource)
+    {
+      return "UTF-8";
+    }
+    return null;
+  }
+
+  public String getMimeType()
+  {
+    if (this.frameworkDataSource instanceof PdfDataSource)
+    {
+      return "application/pdf";
+    }
+    if (this.frameworkDataSource instanceof TextDataSource)
+    {
+      return "text/plain";
+    }
+
+    return null;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java
new file mode 100644
index 0000000..fbafafe
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java
@@ -0,0 +1,52 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import java.io.InputStream;
+
+/**
+ * Adapter that converts an API DataSource to a framework PdfDataSource.
+ * 
+ * @author wprinz
+ */
+public class PdfDataSourceAdapter implements at.gv.egiz.pdfas.framework.input.PdfDataSource
+{
+  /**
+   * The API DataSource to be adapted to a framework PdfDataSource.
+   */
+  protected at.gv.egiz.pdfas.api.io.DataSource apiDataSource = null;
+
+  /**
+   * Constructor.
+   * @param apiDataSource The API DataSource to be adapted to a framework PdfDataSource.
+   */
+  public PdfDataSourceAdapter(at.gv.egiz.pdfas.api.io.DataSource apiDataSource)
+  {
+    this.apiDataSource = apiDataSource;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return this.apiDataSource.createInputStream();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    return this.apiDataSource.getAsByteArray();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return this.apiDataSource.getLength();
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java
new file mode 100644
index 0000000..875c3d9
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java
@@ -0,0 +1,87 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.knowcenter.wag.egov.egiz.pdf.EGIZDate;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+
+/**
+ * Adapter that converts a framework SignatureHolder to an API
+ * SignatureInformation.
+ * 
+ * @author wprinz
+ */
+public class SignatureInformationAdapter implements SignatureInformation
+{
+  /**
+   * The framework SignatureHolder to be adapted to an API SignatureInformation.
+   */
+  protected SignatureHolder signatureHolder = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param signatureHolder
+   *          The framework SignatureHolder to be adapted to an API
+   *          SignatureInformation.
+   */
+  public SignatureInformationAdapter(SignatureHolder signatureHolder)
+  {
+    this.signatureHolder = signatureHolder;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignedData()
+   */
+  public DataSource getSignedData()
+  {
+    return new DataSourceApiAdapter(this.signatureHolder.getDataSource());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getInternalSignatureInformation()
+   */
+  public Object getInternalSignatureInformation()
+  {
+    return this.signatureHolder;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignatureType()
+   */
+  public String getSignatureType()
+  {
+    if (this.signatureHolder.getSignatureObject().isBinary())
+    {
+      return Constants.SIGNATURE_TYPE_BINARY;
+    }
+    return Constants.SIGNATURE_TYPE_TEXTUAL;
+  }
+
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignerCertificate()
+   */
+  public X509Certificate getSignerCertificate()
+  {
+    return this.signatureHolder.getSignatureObject().getX509Cert().getX509Certificate();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSigningTime()
+   */
+  public Date getSigningTime()
+  {
+    String date_value = this.signatureHolder.getSignatureObject().getSignationDate();
+    Date date = EGIZDate.parseDateFromString(date_value);
+    return date;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
new file mode 100644
index 0000000..0d2bfdd
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
@@ -0,0 +1,56 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import at.gv.egiz.pdfas.api.commons.SignatureProfile;
+
+/**
+ * Holds the data of a signature profile.
+ * 
+ * @author wprinz
+ */
+public class SignatureProfileImpl implements SignatureProfile
+{
+
+  /**
+   * The profile identifier.
+   */
+  protected String profileId = null;
+
+  /**
+   * The MOA key identifiert of this profile.
+   */
+  protected String moaKeyIdentifier = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param profileId
+   *          The profile identifier.
+   * @param moaKeyIdentifier
+   *          The MOA key identifiert of this profile.
+   */
+  public SignatureProfileImpl(String profileId, String moaKeyIdentifier)
+  {
+    this.profileId = profileId;
+    this.moaKeyIdentifier = moaKeyIdentifier;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getProfileId()
+   */
+  public String getProfileId()
+  {
+    return this.profileId;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getMOAKeyIdentifier()
+   */
+  public String getMOAKeyIdentifier()
+  {
+    return this.moaKeyIdentifier;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java
new file mode 100644
index 0000000..4b34d6f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java
@@ -0,0 +1,52 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.commons;
+
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.pdfas.api.io.TextBased;
+import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
+
+/**
+ * Adapter that converts an API DataSource to a framework TextDataSource.
+ * 
+ * @author wprinz
+ */
+public class TextDataSourceAdapter extends TextDataSourceImpl
+{
+  /**
+   * The API DataSource to be adapted to a framework TextDataSource.
+   */
+  protected at.gv.egiz.pdfas.api.io.DataSource apiDataSource = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param apiDataSource
+   *          The API DataSource to be adapted to a framework TextDataSource.
+   * @throws UnsupportedEncodingException
+   */
+  public TextDataSourceAdapter(at.gv.egiz.pdfas.api.io.DataSource apiDataSource) throws UnsupportedEncodingException
+  {
+    super(null);
+    this.apiDataSource = apiDataSource;
+
+    if (this.apiDataSource instanceof TextBased)
+    {
+      TextBased tb = (TextBased) this.apiDataSource;
+      this.text = tb.getText();
+    }
+    else
+    {
+      byte[] data = this.apiDataSource.getAsByteArray();
+      String characterEncoding = this.apiDataSource.getCharacterEncoding();
+      if (characterEncoding == null)
+      {
+        throw new UnsupportedEncodingException("The characterEncoding must not be null. Specify a correct encoding.");
+      }
+      this.text = new String(data, characterEncoding);
+    }
+    assert this.text != null;
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java
new file mode 100644
index 0000000..a0c32aa
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java
@@ -0,0 +1,73 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.sign;
+
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition;
+import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos;
+
+/**
+ * Adapter that converts from a framework ActualTablePos to an API
+ * ActualSignaturePosition.
+ * 
+ * @author wprinz
+ * 
+ */
+public class ActualSignaturePositionAdapter implements SignaturePosition
+{
+  /**
+   * The framework ActualTablePos.
+   */
+  protected ActualTablePos atp = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param actualTablePos
+   *          The framework ActualTablePos.
+   */
+  public ActualSignaturePositionAdapter(ActualTablePos actualTablePos)
+  {
+    this.atp = actualTablePos;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getPage()
+   */
+  public int getPage()
+  {
+    return this.atp.page;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getX()
+   */
+  public float getX()
+  {
+    return this.atp.x;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getY()
+   */
+  public float getY()
+  {
+    return this.atp.y;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getWidth()
+   */
+  public float getWidth()
+  {
+    return this.atp.width;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getHeight()
+   */
+  public float getHeight()
+  {
+    return this.atp.height;
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java
new file mode 100644
index 0000000..7161f5b
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java
@@ -0,0 +1,75 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.sign;
+
+import java.security.cert.X509Certificate;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition;
+
+/**
+ * Implementation of the SignResult interface.
+ * 
+ * @author wprinz
+ */
+public class SignResultImpl implements SignResult
+{
+  /**
+   * The filled output DataSink.
+   */
+  protected DataSink outputDocument = null;
+
+  /**
+   * The signer certificate.
+   */
+  protected X509Certificate signerCertificate = null;
+
+  /**
+   * The signature position.
+   */
+  protected SignaturePosition signaturePosition = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param outputDocument
+   *          The filled output DataSink.
+   * @param signerCertificate
+   *          The signer certificate.
+   * @param signaturePosition
+   *          The signature position.
+   */
+  public SignResultImpl(DataSink outputDocument, X509Certificate signerCertificate, SignaturePosition signaturePosition)
+  {
+    this.outputDocument = outputDocument;
+    this.signerCertificate = signerCertificate;
+    this.signaturePosition = signaturePosition;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.SignResult#getOutputDocument()
+   */
+  public DataSink getOutputDocument()
+  {
+    return this.outputDocument;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.SignResult#getSignaturePosition()
+   */
+  public SignaturePosition getSignaturePosition()
+  {
+    return this.signaturePosition;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.sign.SignResult#getSignerCertificate()
+   */
+  public X509Certificate getSignerCertificate()
+  {
+    return this.signerCertificate;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java
new file mode 100644
index 0000000..d5803f8
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java
@@ -0,0 +1,51 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.verify;
+
+import at.gv.egiz.pdfas.api.verify.SignatureCheck;
+
+/**
+ * @author wprinz
+ */
+public class SignatureCheckImpl implements SignatureCheck
+{
+  /**
+   * The check code.
+   */
+  protected int code = -1;
+  
+  /**
+   * The check code message.
+   */
+  protected String message = null;
+  
+  
+
+  /**
+   * @param code The check code.
+   * @param message The check code message.
+   */
+  public SignatureCheckImpl(int code, String message)
+  {
+    this.code = code;
+    this.message = message;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.SignatureCheck#getCode()
+   */
+  public int getCode()
+  {
+    return this.code;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.SignatureCheck#getMessage()
+   */
+  public String getMessage()
+  {
+    return this.message;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java
new file mode 100644
index 0000000..d66097a
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java
@@ -0,0 +1,126 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.verify;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.verify.SignatureCheck;
+import at.gv.egiz.pdfas.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+
+/**
+ * Implements the VerifyResult interface.
+ * 
+ * @author wprinz
+ */
+public class VerifyResultAdapter extends SignatureInformationAdapter implements VerifyResult
+{
+  protected SignatureResponse sigRes = null;
+
+  protected Date vTime = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param sigRes
+   *          The SignatureResponse.
+   * @param sh
+   *          The SignatureHolder.
+   * @param verificationTime
+   *          The time of verification. This is directly returned by {@link #getVerificationTime()}
+   */
+  public VerifyResultAdapter(SignatureResponse sigRes, SignatureHolder sh, Date verificationTime)
+  {
+    super(sh);
+    this.sigRes = sigRes;
+    this.vTime = verificationTime;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getCertificateCheck()
+   */
+  public SignatureCheck getCertificateCheck()
+  {
+    return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getCertificateCheckCode()), this.sigRes.getCertificateCheckInfo());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getManifestCheckCode()
+   */
+  public SignatureCheck getManifestCheckCode()
+  {
+    return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getSignatureManifestCheckCode()), this.sigRes.getSignatureManifestCheckInfo());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getValueCheckCode()
+   */
+  public SignatureCheck getValueCheckCode()
+  {
+    return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getSignatureCheckCode()), this.sigRes.getSignatureCheckInfo());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getVerificationTime()
+   */
+  public Date getVerificationTime()
+  {
+    return this.vTime;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#isQualifiedCertificate()
+   */
+  public boolean isQualifiedCertificate()
+  {
+    return this.sigRes.isQualifiedCertificate();
+  }
+  
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getPublicProperties()
+   */
+  public List getPublicProperties()
+  {
+    try
+    {
+      return this.sigRes.getPublicProperties();
+    }
+    catch (SettingNotFoundException e)
+    {
+      e.printStackTrace();
+      return new ArrayList();
+    }
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getInternalSignatureInformation()
+   */
+  public Object getInternalSignatureInformation()
+  {
+    return null;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignerCertificate()
+   */
+  public X509Certificate getSignerCertificate()
+  {
+    // TODO this should be the same as the signature holder's cert.
+    return this.sigRes.getCertificate().getX509Certificate();
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getHashInputData()
+   */
+  public String getHashInputData()
+  {
+    return this.sigRes.getHashInputData();
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java
new file mode 100644
index 0000000..e7cc79d
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java
@@ -0,0 +1,38 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.impl.api.verify;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.verify.VerifyResults;
+
+/**
+ * @author wprinz
+ */
+public class VerifyResultsImpl implements VerifyResults
+{
+  /**
+   * The results.
+   */
+  protected List results = null;
+
+  /**
+   * Constructor.
+   * 
+   * @param results
+   *          The results.
+   */
+  public VerifyResultsImpl(List results)
+  {
+    this.results = results;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.verify.VerifyResults#getResults()
+   */
+  public List getResults()
+  {
+    return this.results;
+  }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java b/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java
index 138b269..2a3fedd 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java
@@ -75,6 +75,17 @@ public class DataSourceHelper
   {
     try
     {
+      return convertInputStreamToByteArrayIOEx(inputStream);
+    }
+    catch (IOException e)
+    {
+      log.error(e);
+      throw new RuntimeException(e);
+    }
+  }
+  
+  public static byte [] convertInputStreamToByteArrayIOEx(InputStream inputStream) throws IOException
+  {
       PerformanceCounters.byteArrays.increment();
 
       ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
@@ -92,12 +103,6 @@ public class DataSourceHelper
       byte [] data = baos.toByteArray();
       
       return data;
-    }
-    catch (IOException e)
-    {
-      log.error(e);
-      throw new RuntimeException(e);
-    }
   }
   
   public static void debugDataSourceToFile(DataSource dataSource, File file)
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java b/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java
index a95cdc6..f308e30 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java
@@ -32,14 +32,14 @@ public final class IncrementalUpdateHelper
     return iui;
   }
 
-  public static void writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, PositioningInstruction pi) throws PresentableException
+  public static IncrementalUpdateInformation writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, PositioningInstruction pi) throws PresentableException
   {
-    writeIncrementalUpdateToDataSink(pdfDataSource, dataSink, pdf_table, pi, null, null);
+    return writeIncrementalUpdateToDataSink(pdfDataSource, dataSink, pdf_table, pi, null, null);
   }
 
-  public static void writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, PositioningInstruction pi, List variable_field_definitions,
+  public static IncrementalUpdateInformation writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, PositioningInstruction pi, List variable_field_definitions,
       List all_field_definitions) throws PresentableException
   {
-    BinarySignature.writeIncrementalUpdate(pdfDataSource, dataSink, pdf_table, pi, variable_field_definitions, all_field_definitions);
+    return BinarySignature.writeIncrementalUpdate(pdfDataSource, dataSink, pdf_table, pi, variable_field_definitions, all_field_definitions);
   }
 }
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java b/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java
index 916abf4..0ed3699 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java
@@ -5,6 +5,7 @@ package at.gv.egiz.pdfas.impl.signator.binary;
 
 import java.util.List;
 
+import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos;
 import at.knowcenter.wag.egov.egiz.sig.SignatureData;
 import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 import at.gv.egiz.pdfas.framework.input.PdfDataSource;
@@ -31,6 +32,8 @@ public class BinarySignatorInformation implements SignatorInformation
   protected int enc_length = -1;
   
   protected SignSignatureObject signSignatureObject = null;
+  
+  protected ActualTablePos atp = null;
 
   /**
    * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignatureData()
@@ -48,4 +51,20 @@ public class BinarySignatorInformation implements SignatorInformation
     this.signSignatureObject = signSignatureObject;
   }
 
+  /**
+   * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignSignatureObject()
+   */
+  public SignSignatureObject getSignSignatureObject()
+  {
+    return this.signSignatureObject;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getActualTablePos()
+   */
+  public ActualTablePos getActualTablePos()
+  {
+    return this.atp;
+  }
+
 }
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java b/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
index b1f1cea..73d4866 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
@@ -296,6 +296,7 @@ public class BinarySignator_1_0_0 implements Signator
     bsi.cert_length = iui.cert_length;
     bsi.enc_start = iui.enc_start;
     bsi.enc_length = iui.enc_length;
+    bsi.atp = iui.actualTablePos;
 
     return bsi;
   }
@@ -312,6 +313,7 @@ public class BinarySignator_1_0_0 implements Signator
     iui.cert_length = bsi.cert_length;
     iui.enc_start = bsi.enc_start;
     iui.enc_length = bsi.enc_length;
+    iui.actualTablePos = bsi.atp;
     
     iui.signed_signature_object = bsi.signSignatureObject;
 
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java b/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java
index c5b18ff..9e5ebb6 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java
@@ -3,6 +3,7 @@
  */
 package at.gv.egiz.pdfas.impl.signator.textual;
 
+import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos;
 import at.knowcenter.wag.egov.egiz.pdf.TablePos;
 import at.knowcenter.wag.egov.egiz.sig.SignatureData;
 import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
@@ -24,6 +25,8 @@ public class TextualSignatorInformation implements SignatorInformation
   protected TablePos pos = null;
 
   public SignSignatureObject signSignatureObject = null;
+  
+  protected ActualTablePos atp = null;
 
   /**
    * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignatureData()
@@ -34,7 +37,6 @@ public class TextualSignatorInformation implements SignatorInformation
   }
 
   /**
-   * 
    * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#setSignSignatureObject(at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
    */
   public void setSignSignatureObject(SignSignatureObject signSignatureObject)
@@ -42,4 +44,19 @@ public class TextualSignatorInformation implements SignatorInformation
     this.signSignatureObject = signSignatureObject;
   }
 
+  /**
+   * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignSignatureObject()
+   */
+  public SignSignatureObject getSignSignatureObject()
+  {
+    return this.signSignatureObject;
+  }
+  
+  /**
+   * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getActualTablePos()
+   */
+  public ActualTablePos getActualTablePos()
+  {
+    return this.atp;
+  }
 }
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java b/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java
index 1714afc..b49803c 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java
@@ -29,6 +29,7 @@ import at.knowcenter.wag.egov.egiz.PdfAS;
 import at.knowcenter.wag.egov.egiz.PdfASID;
 import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
 import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation;
 import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
 import at.knowcenter.wag.egov.egiz.pdf.TablePos;
 import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
@@ -127,7 +128,8 @@ public class TextualSignator_1_0_0 implements Signator
 
       PositioningInstruction pi = PdfAS.determineTablePositioning(tsi.pos, tsi.profile, tsi.originalDocument, pdf_table);
 
-      IncrementalUpdateHelper.writeIncrementalUpdateToDataSink(tsi.originalDocument, dataSink, pdf_table, pi);
+      IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdateToDataSink(tsi.originalDocument, dataSink, pdf_table, pi);
+      tsi.atp = iui.actualTablePos;
 
 //      OutputStream os = dataSink.createOutputStream(PdfAS.PDF_MIME_TYPE);
 //      os.write(signed_iui.signed_pdf);
diff --git a/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java b/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java
new file mode 100644
index 0000000..bf74ed5
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java
@@ -0,0 +1,87 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+
+/**
+ * @author wprinz
+ * 
+ */
+public class ByteArrayDataSink implements DataSink
+{
+  /**
+   * The byte output stream.
+   */
+  ByteArrayOutputStream baos = null;
+
+  /**
+   * The mime type.
+   */
+  protected String mimeType = null;
+
+  /**
+   * The character encoding.
+   */
+  protected String characterEncoding = null;
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType) throws IOException
+  {
+    return createOutputStream(mimeType, null);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String,
+   *      java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType, String characterEncoding) throws IOException
+  {
+    this.mimeType = mimeType;
+    this.characterEncoding = characterEncoding;
+    this.baos = new ByteArrayOutputStream();
+    return this.baos;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.mimeType;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.characterEncoding;
+  }
+
+  /**
+   * Returns the byte data, or null if none available.
+   * 
+   * <p>
+   * Note that internally, this just calls the {@link ByteArrayOutputStream#toByteArray()} method.
+   * </p>
+   * 
+   * @return Returns the byte data, or null if none available.
+   */
+  public byte [] getData()
+  {
+    if (this.baos == null)
+    {
+      return null;
+    }
+    return this.baos.toByteArray();
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java b/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java
new file mode 100644
index 0000000..37726df
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java
@@ -0,0 +1,95 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * A byte array backed DataSource.
+ * 
+ * @author wprinz
+ */
+public class ByteArrayDataSource implements DataSource
+{
+
+  /**
+   * The byte array.
+   */
+  protected byte[] data = null;
+
+  /**
+   * The mime type.
+   */
+  protected String mimeType = null;
+
+  /**
+   * The character encoding.
+   */
+  protected String characterEncoding = null;
+
+  /**
+   * @param data
+   * @param mimeType
+   */
+  public ByteArrayDataSource(byte[] data, String mimeType)
+  {
+    this(data, mimeType, null);
+  }
+
+  /**
+   * @param data
+   * @param mimeType
+   * @param characterEncoding
+   */
+  public ByteArrayDataSource(byte[] data, String mimeType, String characterEncoding)
+  {
+    this.data = data;
+    this.mimeType = mimeType;
+    this.characterEncoding = characterEncoding;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return new ByteArrayInputStream(this.data);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    return this.data;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.characterEncoding;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.mimeType;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return this.data.length;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java b/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java
new file mode 100644
index 0000000..184dd09
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java
@@ -0,0 +1,96 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.io.FileBased;
+
+/**
+ * @author wprinz
+ * 
+ */
+public class FileBasedDataSink implements DataSink, FileBased
+{
+  protected File file = null;
+
+  protected String mimeType = null;
+
+  protected String characterEncoding = null;
+
+  
+  
+  /**
+   * @param file
+   * @throws IOException 
+   */
+  public FileBasedDataSink(File file) throws IOException
+  {
+    if (!file.exists())
+    {
+      file.createNewFile();
+    }
+    if (!file.isFile())
+    {
+      throw new IOException("The file '" + file + "' is not a normal file.");
+    }
+    if (!file.canWrite())
+    {
+      throw new IOException("The file '" + file + "' cannot be written.");
+    }
+
+    this.file = file;
+  }
+
+  /**
+   * @throws FileNotFoundException
+   * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType) throws FileNotFoundException
+  {
+    return createOutputStream(mimeType, null);
+  }
+
+  /**
+   * @throws FileNotFoundException
+   * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String,
+   *      java.lang.String)
+   */
+  public OutputStream createOutputStream(String mimeType, String characterEncoding) throws FileNotFoundException
+  {
+    this.mimeType = mimeType;
+    this.characterEncoding = characterEncoding;
+    return new FileOutputStream(this.file);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.mimeType;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSink#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.characterEncoding;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.FileBased#getFile()
+   */
+  public File getFile()
+  {
+    return this.file;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java b/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java
new file mode 100644
index 0000000..fd56bfe
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java
@@ -0,0 +1,121 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.io.FileBased;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+
+/**
+ * A FileBased DataSource implementation.
+ * 
+ * @author wprinz
+ */
+public class FileBasedDataSource implements DataSource, FileBased
+{
+  protected File file = null;
+
+  protected String mimeType = null;
+
+  protected String characterEncoding = null;
+
+  protected byte[] cache = null;
+
+  /**
+   * @param file
+   * @param mimeType
+   * @throws IOException
+   */
+  public FileBasedDataSource(File file, String mimeType) throws IOException
+  {
+    this(file, mimeType, null);
+  }
+
+  /**
+   * @param file
+   * @param mimeType
+   * @param characterEncoding
+   * @throws IOException
+   */
+  public FileBasedDataSource(File file, String mimeType, String characterEncoding) throws IOException
+  {
+    if (file == null)
+    {
+      throw new IllegalArgumentException("The file must not be null.");
+    }
+    if (mimeType == null)
+    {
+      throw new IllegalArgumentException("The mimeType must not be null.");
+    }
+    if (!file.exists())
+    {
+      throw new FileNotFoundException("The file '" + file + "' does not exist.");
+    }
+    if (!file.canRead())
+    {
+      throw new IOException("The file '" + file + "' cannot be read.");
+    }
+
+    this.file = file;
+    this.mimeType = mimeType;
+    this.characterEncoding = characterEncoding;
+    this.cache = DataSourceHelper.convertInputStreamToByteArrayIOEx(new FileInputStream(this.file));
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return new ByteArrayInputStream(this.cache);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    return this.cache;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return this.cache.length;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.mimeType;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.characterEncoding;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.FileBased#getFile()
+   */
+  public File getFile()
+  {
+    return this.file;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java b/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
new file mode 100644
index 0000000..5be2148
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
@@ -0,0 +1,103 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.pdfas.api.io.TextBased;
+
+/**
+ * FileBased DataSource that is TextBased.
+ * 
+ * @author wprinz
+ */
+public class FileBasedTextBasedDataSource extends FileBasedDataSource implements TextBased
+{
+  protected String text = null;
+
+  /**
+   * @param file
+   * @param mimeType
+   * @param characterEncoding
+   * @throws IOException
+   */
+  public FileBasedTextBasedDataSource(File file, String mimeType, String characterEncoding) throws IOException
+  {
+    super(file, mimeType, characterEncoding);
+    if (characterEncoding == null)
+    {
+      throw new IllegalArgumentException("The characterEncoding must not be null.");
+    }
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return new ByteArrayInputStream(this.cache);
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    return this.cache;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return this.cache.length;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return this.mimeType;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return this.characterEncoding;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.FileBased#getFile()
+   */
+  public File getFile()
+  {
+    return this.file;
+  }
+
+  public String getText()
+  {
+    if (this.text == null)
+    {
+      try
+      {
+        this.text = new String(this.cache, this.characterEncoding);
+      }
+      catch (UnsupportedEncodingException e)
+      {
+        e.printStackTrace();
+        throw new RuntimeException(e);
+      }
+    }
+    return this.text;
+  }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java b/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
new file mode 100644
index 0000000..d8b879f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
@@ -0,0 +1,96 @@
+/**
+ * 
+ */
+package at.gv.egiz.pdfas.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.io.TextBased;
+
+/**
+ * A String TextBased DataSource.
+ * 
+ * @author wprinz
+ * 
+ */
+public class StringTextBasedDataSource implements DataSource, TextBased
+{
+  /**
+   * The text.
+   */
+  protected String text = null;
+
+  protected byte[] cache = null;
+
+  /**
+   * @param text
+   */
+  public StringTextBasedDataSource(String text)
+  {
+    this.text = text;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream()
+   */
+  public InputStream createInputStream()
+  {
+    return new ByteArrayInputStream(getAsByteArray());
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray()
+   */
+  public byte[] getAsByteArray()
+  {
+    if (cache == null)
+    {
+      try
+      {
+        this.cache = this.text.getBytes("UTF-8");
+      }
+      catch (UnsupportedEncodingException e)
+      {
+        e.printStackTrace();
+        throw new RuntimeException(e);
+      }
+    }
+    return this.cache;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getLength()
+   */
+  public int getLength()
+  {
+    return getAsByteArray().length;
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType()
+   */
+  public String getMimeType()
+  {
+    return "text/plain";
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding()
+   */
+  public String getCharacterEncoding()
+  {
+    return "UTF-8";
+  }
+
+  /**
+   * @see at.gv.egiz.pdfas.api.io.TextBased#getText()
+   */
+  public String getText()
+  {
+    return this.text;
+  }
+
+}
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
index 6fc7b84..9aef071 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
@@ -17,31 +17,27 @@
  */
 package at.knowcenter.wag.egov.egiz;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 import java.util.Vector;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser;
 import at.gv.egiz.pdfas.exceptions.ErrorCode;
-import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
-import at.gv.egiz.pdfas.impl.input.DelimitedInputStream;
-import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
-import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
-import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.gv.egiz.pdfas.framework.input.PdfDataSource;
-import at.gv.egiz.pdfas.framework.input.TextDataSource;
 import at.gv.egiz.pdfas.framework.output.DataSink;
 import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
 import at.gv.egiz.pdfas.web.VerifySessionInformation;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
@@ -62,7 +58,6 @@ import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
 import at.knowcenter.wag.egov.egiz.pdf.TablePos;
 import at.knowcenter.wag.egov.egiz.pdf.TextualSignature;
 import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
-import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory;
 import at.knowcenter.wag.egov.egiz.sig.SignatureData;
 import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
 import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
@@ -740,7 +735,7 @@ public abstract class PdfAS
     return true;
   }
 
-  public static List verifySignatureHolders(List signature_holders, String connectorType) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
+  public static List verifySignatureHolders(List signature_holders, String connectorType, boolean returnHashInputData, Date verificationTime) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
   {
     List results = new ArrayList();
     for (int i = 0; i < signature_holders.size(); i++)
@@ -757,7 +752,7 @@ public abstract class PdfAS
       // (holder.signature_object.isTextual() ? "textual" : "binary"));
       // logger_.debug(holder.signature_object.toString());
 
-      SignatureResponse result = verify(holder, connectorType);
+      SignatureResponse result = verify(holder, connectorType, returnHashInputData, verificationTime);
       results.add(result);
 
       // logger_.debug();
@@ -809,7 +804,7 @@ public abstract class PdfAS
    * @throws ConnectorException 
    * @throws ConnectorFactoryException 
    */
-  public static SignatureResponse verify(SignatureHolder signature_holder, String connectorType) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException, ConnectorFactoryException
+  public static SignatureResponse verify(SignatureHolder signature_holder, String connectorType, boolean returnHashInputData, Date verificationTime) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException, ConnectorFactoryException
   {
     // String text_to_be_verified = signature_holder.getSignedText();
     // logger_.debug("verify text_to_be_verified"+text_to_be_verified);
@@ -844,10 +839,14 @@ public abstract class PdfAS
     String profile = so_to_be_verified.getSignatureTypeDefinition().getType();
 //    Connector c = ConnectorChooser.chooseCommandlineConnectorForVerify(connector, so_to_be_verified.getKZ(), so.id, profile);
     String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForVerify(connectorType, so_to_be_verified.getKZ(), so.id, profile);
-    Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, profile, null);
+    
+    ConnectorParameters cp = new ConnectorParameters();
+    cp.setProfileId(profile);
+    cp.setReturnHashInputData(returnHashInputData);
+    cp.setVerificationTime(verificationTime);
+    Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
 
     return c.doVerify(sd, so);
-
   }
 
   public static SignatureResponse verifyWeb(SignatureHolder signature_holder, String connector, String loc_ref) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException
@@ -992,11 +991,13 @@ public abstract class PdfAS
 //    signCommandline(pdfDataSource, dataSink, signatorId, connectorId, profile, pos);
 //  }
   
-  public static void signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, TablePos pos) throws PresentableException
+  public static SignatorInformation signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, TablePos pos) throws PresentableException
   {
     at.gv.egiz.pdfas.framework.signator.Signator signator = at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId);
 
-    Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, profile, null);
+    ConnectorParameters cp = new ConnectorParameters();
+    cp.setProfileId(profile);
+    Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
 
     // SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, ConnectorFactory.needsSIG_ID(connector));
     SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, CommandlineConnectorChooser.needsSigId(connectorId));
@@ -1006,6 +1007,8 @@ public abstract class PdfAS
     si.setSignSignatureObject(sso);
 
     signator.finishSign(si, dataSink);
+    
+    return si;
   }
   
   /**
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java b/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
index 97929af..054da24 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
@@ -344,6 +344,21 @@ public class SettingsReader implements Serializable
   {
     return getInstance(null);
   }
+  
+  /**
+   * Reloads the Settings file.
+   * 
+   * <p>
+   * Subsequent calls to getInstance will return the new settings.
+   * </p>
+   * 
+   * @throws SettingsException f.e.
+   */
+  public synchronized static void createInstance () throws SettingsException
+  {
+    instance_ = null;
+    getInstance();
+  }
 
   /**
    * This method returns an synchronized instance of this class. The settings
@@ -663,6 +678,13 @@ public class SettingsReader implements Serializable
     }
   }
 
+  public static void initialize(String base_dir)
+  {
+    RESOURCES_PATH = base_dir + FILE_SEP; //CATALINA_HOME + FILE_SEP + WEB_APPL_DIR;
+    CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
+    CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
+  }
+  
   /**
    * Initializes the paths of the SettingsReader for web application usage.
    * 
@@ -672,9 +694,10 @@ public class SettingsReader implements Serializable
    */
   public static void initializeForWeb(String base_dir)
   {
-    RESOURCES_PATH = base_dir + FILE_SEP; //CATALINA_HOME + FILE_SEP + WEB_APPL_DIR;
-    CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
-    CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
+    initialize(base_dir);
+//    RESOURCES_PATH = base_dir + FILE_SEP; //CATALINA_HOME + FILE_SEP + WEB_APPL_DIR;
+//    CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
+//    CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
   }
 
   /**
@@ -682,9 +705,10 @@ public class SettingsReader implements Serializable
    */
   public static void initializeForCommandLine()
   {
-    RESOURCES_PATH = USER_DIR + FILE_SEP;
-    CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
-    CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
+    initialize(USER_DIR);
+//    RESOURCES_PATH = USER_DIR + FILE_SEP;
+//    CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
+//    CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
   }
   
   static {
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java b/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
index 72565d9..11bd0e0 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
@@ -156,6 +156,8 @@ public abstract class Main
    * @param args
    *          The commandline arguments.
    * @throws IOException
+   * 
+   * @deprecated use {@link at.gv.egiz.pdfas.commandline.Main} instead
    */
   public static void main(String[] args) throws IOException
   {
@@ -639,7 +641,7 @@ public abstract class Main
       holders_to_verify.add(holder);
     }
     
-    List results = PdfAS.verifySignatureHolders(holders_to_verify, connector);
+    List results = PdfAS.verifySignatureHolders(holders_to_verify, connector, false, null);
 
     return results;
   }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java b/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java
index 218109d..e8ef988 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java
@@ -17,6 +17,8 @@
  */
 package at.knowcenter.wag.egov.egiz.exceptions;
 
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+
 /**
  * This exception should be the base for all exceptions that are to be presented
  * to the user.
@@ -27,56 +29,32 @@ package at.knowcenter.wag.egov.egiz.exceptions;
  * can present according texts.
  * </p>
  * 
+ * @see PdfAsException
+ * 
  * @author wprinz
  */
-public class PresentableException extends Exception
+public class PresentableException extends PdfAsException
 {
 
   /**
    * SVUID.
    */
   private static final long serialVersionUID = -102406558526000792L;
-  
-  protected int errorCode = -1;
 
-  /**
-   * @param message
-   */
-  public PresentableException(int errorCode, String message)
+  public PresentableException(int errorCode, String message, Throwable cause)
   {
-    super(message);
-    
-    this.errorCode = errorCode;
+    super(errorCode, message, cause);
   }
 
-  /**
-   * @param message
-   * @param cause
-   */
-  public PresentableException(int errorCode, String message, Throwable cause)
+  public PresentableException(int errorCode, String message)
   {
-    super(message, cause);
-    
-    this.errorCode = errorCode;
+    super(errorCode, message);
   }
 
-  /**
-   * @param cause
-   */
   public PresentableException(int errorCode, Throwable cause)
   {
-    super(cause);
-    
-    this.errorCode = errorCode;
+    super(errorCode, cause);
   }
   
-  /**
-   * Returns the error code of this exception.
-   * @return Returns the error code of this exception.
-   */
-  public int getErrorCode ()
-  {
-    return this.errorCode;
-  }
 
 }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
index 4219475..4b9a2aa 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
@@ -537,6 +537,14 @@ public class AbsoluteTextSignature
   {
     int block_start_index = ((FoundKey) block.found_keys.get(0)).getStartIndex();
     int block_end_index = block.end_index;
+    
+    if (block_start_index == 0 && block_end_index == text.length())
+    {
+      // the block is the whole text - the rest text is empty.
+      // This may happen if a (no-text) empty document contains a binary signature.
+      // Then the "signed text" of the binary signature is empty.
+      return "";
+    }
 
     if (block_end_index == text.length())
     {
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java
new file mode 100644
index 0000000..f58e9f8
--- /dev/null
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java
@@ -0,0 +1,22 @@
+/**
+ * 
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+/**
+ * The actual table position where the signature was placed after signation.
+ * @author wprinz
+ */
+public class ActualTablePos
+{
+  public int page;
+  
+  public float x;
+  
+  public float y;
+  
+  public float width;
+  
+  public float height;
+
+}
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
index 677990b..7a5af6b 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
@@ -737,6 +737,14 @@ public abstract class BinarySignature
       // table_position, content);
 
       content.addTemplate(table_template, pi.getX(), pi.getY() - pdf_table.getTotalHeight());
+      
+      ActualTablePos atp = new ActualTablePos();
+      atp.page = pi.getPage();
+      atp.x = pi.getX();
+      atp.y = pi.getY(); // TODO is this correct or flipped?
+      atp.width = pdf_table.getTotalWidth();
+      atp.height = pdf_table.getTotalHeight();
+      iui.actualTablePos = atp;
 
       // For debugging print a 100x100 grid
       // {
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java
index f818f59..77f1150 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java
@@ -172,5 +172,10 @@ public class IncrementalUpdateInformation implements Serializable
    * For signing: the profile.
    */
   public String signProfile;
+  
+  /**
+   * The actual position where the table was written.
+   */
+  public ActualTablePos actualTablePos;
 
 }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java
index 603e0fe..deedb6d 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java
@@ -102,6 +102,8 @@ public class SignatureResponse
   private boolean qualifiedCertificate = false;
   // [tknall] stop qualified certificate
   
+  protected String hashInputData = null;
+  
   // /**
   // * Flag the marks that the response is an error response
   // */
@@ -423,6 +425,16 @@ public class SignatureResponse
     this.certificate_ = certificate;
   }
 
+  public String getHashInputData()
+  {
+    return this.hashInputData;
+  }
+
+  public void setHashInputData(String hashInputData)
+  {
+    this.hashInputData = hashInputData;
+  }
+
   /**
    * Returns a list of Strings each stating one public property of the
    * certificate.
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java
index 19b28e7..13fdf2f 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java
@@ -319,6 +319,16 @@ public class SignatureTypes
     }
     return instance_;
   }
+  
+  /**
+   * Reloads the instance.
+   * @throws SignatureTypesException
+   */
+  public static void createInstance() throws SignatureTypesException
+  {
+    instance_ = null;
+    getInstance();
+  }
 
   /**
    * This method load the signature definitions
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
index 5b16211..cbdee42 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
@@ -6,6 +6,7 @@ package at.knowcenter.wag.egov.egiz.sig.connectors;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.PdfASID;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
@@ -46,7 +47,9 @@ public final class ConnectorChooser
     }
 
     log.debug("choosing locref detached BKU connector.");
-    return new LocRefDetachedBKUConnector(profile, loc_ref_url);
+    ConnectorParameters cp = new ConnectorParameters();
+    cp.setProfileId(profile);
+    return new LocRefDetachedBKUConnector(cp, loc_ref_url);
   }
 
   public static Connector chooseWebConnectorForSign(String connector,
@@ -67,7 +70,9 @@ public final class ConnectorChooser
     // Loc_Ref-Connector
 //    return new DetachedLocRefMOAConnector(profile, loc_ref_url);
     // SwA-Connector
-    return new MOASoapWithAttachmentConnector(profile);
+    ConnectorParameters cp = new ConnectorParameters();
+    cp.setProfileId(profile);
+    return new MOASoapWithAttachmentConnector(cp);
   }
 
 //  public static Connector chooseCommandlineConnectorForSign(String connector,
@@ -147,7 +152,9 @@ public final class ConnectorChooser
     {
       log.debug("sig_kz version is 1.1.0 -> choosing detached (loc ref) connector.");
 
-      return new LocRefDetachedBKUConnector(profile, loc_ref_url);
+      ConnectorParameters cp = new ConnectorParameters();
+      cp.setProfileId(profile);
+      return new LocRefDetachedBKUConnector(cp, loc_ref_url);
     }
 
     throw new ConnectorException(310, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown.");
@@ -183,7 +190,9 @@ public final class ConnectorChooser
       // the following line is used in connection with LocRef-Connector
 //      return new DetachedLocRefMOAConnector(profile, loc_ref_url);
       // the following line is uesed in connection with SwA-Connector
-      return new MOASoapWithAttachmentConnector(profile);
+      ConnectorParameters cp = new ConnectorParameters();
+      cp.setProfileId(profile);
+      return new MOASoapWithAttachmentConnector(cp);
     }
 
     throw new ConnectorException(310, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown.");
@@ -293,7 +302,9 @@ public final class ConnectorChooser
     {
       log.debug("sig_app is BKU ==> DetachedMultipartBKUConnector"); //$NON-NLS-1$
 
-      return new MultipartDetachedBKUConnector(profile);
+      ConnectorParameters cp = new ConnectorParameters();
+      cp.setProfileId(profile);
+      return new MultipartDetachedBKUConnector(cp);
     }
     if (sig_app.equals(MOA))
     {
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
index 18cf76d..149065c 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
@@ -117,6 +117,16 @@ public final class TemplateReplaces
    * The placeholder text in the template to be replaced by the trust profile ID.
    */
   public static final String TRUST_PROFILE_ID_REPLACE = "TrustProfileIDReplace"; //$NON-NLS-1$
+
+  /**
+   * The placeholder text in the template to be replaced by the return hash input data element.
+   */
+  public static final String RETURN_HASH_INPUT_DATA_REPLACE = "ReturnHashInputDataReplace"; //$NON-NLS-1$
+
+  /**
+   * The placeholder text in the template to be replaced by the dateTime element.
+   */
+  public static final String DATE_TIME_REPLACE = "DateTimeReplace"; // $NON-NLS-1$
   
   /**
    * The placeholder text in the template to be replaced by the Base64 content.
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
index 8f0b79e..1ddd327 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
@@ -7,12 +7,17 @@ import java.io.UnsupportedEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
 import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -421,12 +426,35 @@ public final class BKUHelper
     Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
     Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
 
+    Pattern hash_data_p_s = Pattern.compile("<HashInputData PartOf=\"SignedInfo\">"); //$NON-NLS-1$
+    Pattern hash_data_p_e = Pattern.compile("</HashInputData>"); //$NON-NLS-1$
+    Matcher hash_data_m_s = hash_data_p_s.matcher(xmlResponse);
+    Matcher hash_data_m_e = hash_data_p_e.matcher(xmlResponse);
+
+
     SignatureResponse sig_res = new SignatureResponse();
 
     // [tknall] start qualified certificate
     sig_res.setQualifiedCertificate(cert_qualified_m.find());
     // [tknall] stop qualified certificate
 
+    if (hash_data_m_s.find() && hash_data_m_e.find())
+    {
+      String hashInputData = xmlResponse.substring(hash_data_m_s.end(), hash_data_m_e.start());
+      
+      Pattern b64_p_s = Pattern.compile("<Base64Content>"); //$NON-NLS-1$
+      Pattern b64_p_e = Pattern.compile("</Base64Content>"); //$NON-NLS-1$
+      Matcher b64_m_s = b64_p_s.matcher(hashInputData);
+      Matcher b64_m_e = b64_p_e.matcher(hashInputData);
+
+      b64_m_s.find();
+      b64_m_e.find();
+      
+      String b64 = hashInputData.substring(b64_m_s.end(), b64_m_e.start());
+
+      sig_res.setHashInputData(b64);
+    }
+
     if (sub_nam_m_s.find() && sub_nam_m_e.find())
     {
       String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
@@ -508,4 +536,27 @@ public final class BKUHelper
     return sig_res;
   }
 
+  public static String formDateTimeElement(Date verificationTime)
+  {
+    return formDateTimeElement(verificationTime, null);
+  }
+
+  public static String formDateTimeElement(Date verificationTime, String namespace)
+  {
+    String nsPrefix = StringUtils.isBlank(namespace) ? "" : (namespace + ":");
+    
+    String dateTimeElement = "";
+    if (verificationTime != null)
+    {
+      log.debug("VerificationTime = " + verificationTime);
+
+      DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+      df.setTimeZone(TimeZone.getTimeZone("UTC"));
+      String dateTime = df.format(verificationTime) + "Z";
+      log.debug("DateTime (VerificationTime in UTC) = " + dateTime);
+      
+      dateTimeElement = "<" + nsPrefix + "DateTime>" + dateTime + "</" + nsPrefix + "DateTime>";
+    };
+    return dateTimeElement;
+  }
 }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
index c84ce8a..f1896d7 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
@@ -11,6 +11,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
@@ -42,6 +43,11 @@ public class DetachedBKUConnector implements Connector, LocalConnector
    */
   private static Log log = LogFactory.getLog(DetachedBKUConnector.class);
 
+  /**
+   * The connector parameters.
+   */
+  protected ConnectorParameters params = null;
+
   /**
    * The environemnt configuration of this connector containing templates and
    * other configurable elements.
@@ -57,14 +63,15 @@ public class DetachedBKUConnector implements Connector, LocalConnector
    * parameters defined in the configuration are used.
    * </p>
    * 
-   * @param profile
-   *          The profile from which the Environment should be assembled.
+   * @param connectorParameters
+   *          The connectot parameters.
    * @throws ConnectorException
    *           f.e.
    */
-  public DetachedBKUConnector(String profile, String loc_ref_content) throws ConnectorException
+  public DetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
   {
-    this.environment = new Environment(profile, loc_ref_content);
+    this.params = connectorParameters;
+    this.environment = new Environment(this.params.getProfileId(), loc_ref_content);
   }
 
   /**
@@ -119,6 +126,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector
     BKUHelper.checkResponseForError(response_string);
 
     SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new DetachedIdFormatter());
+    so.response_properties = response_properties;
 
     log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
     return so;
@@ -309,6 +317,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector
 
     String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
     verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent());
+    verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl"));
 
     return verify_request_xml;
   }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
index 92b7b91..fc29457 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
@@ -3,6 +3,7 @@
  */
 package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
 
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 
 /**
@@ -13,13 +14,13 @@ public class LocRefDetachedBKUConnector extends DetachedBKUConnector
 {
 
   /**
-   * @param profile
+   * @param connectorParameters
    * @param loc_ref_content
    * @throws ConnectorException
    */
-  public LocRefDetachedBKUConnector(String profile, String loc_ref_content) throws ConnectorException
+  public LocRefDetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
   {
-    super(profile, loc_ref_content);
+    super(connectorParameters, loc_ref_content);
   }
 
 }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
index a2d4dc0..6f189af 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
@@ -3,6 +3,7 @@
  */
 package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
 
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 
 /**
@@ -13,9 +14,9 @@ public class MultipartDetachedBKUConnector extends DetachedBKUConnector
 {
   protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
 
-  public MultipartDetachedBKUConnector(String profile) throws ConnectorException
+  public MultipartDetachedBKUConnector(ConnectorParameters connectorParameters) throws ConnectorException
   {
-    super(profile, MULTIPART_LOC_REF_CONTENT);
+    super(connectorParameters, MULTIPART_LOC_REF_CONTENT);
   }
 
 }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
index 3bf0719..b31d1ec 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
@@ -10,6 +10,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
@@ -173,7 +174,9 @@ public class DetachedLocRefMOAConnector implements Connector
     String xml_content = null;
     if (!SigKZIDHelper.isMOASigned(so))
     {
-      DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.environment.getProfile(), "not needed here");
+      ConnectorParameters cp = new ConnectorParameters();
+      cp.setProfileId(this.environment.getProfile());
+      DetachedBKUConnector bku_connector = new DetachedBKUConnector(cp, "not needed here");
       xml_content = bku_connector.prepareXMLContent(data, so);
     }
     else
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
index 34bcdc6..4cb4ec2 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
@@ -4,12 +4,19 @@
 package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
 
 import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Properties;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
 import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
 import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
@@ -25,7 +32,6 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
 import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
 import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
-import at.knowcenter.wag.egov.egiz.tools.DebugHelper;
 import at.knowcenter.wag.egov.egiz.tools.FileHelper;
 
 /**
@@ -46,12 +52,20 @@ public class MOASoapWithAttachmentConnector implements Connector
 
   protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
   
+  protected static final String RETURN_HASH_INPUT_DATA = "<ReturnHashInputData/>"; //$NON-NLS-1$
+  
+  /**
+   * The connector parameters.
+   */
+  protected ConnectorParameters params = null;
+
   /**
    * The environemnt configuration of this connector containing templates and
    * other configurable elements.
    */
   protected Environment environment = null;
-
+  
+   
   /**
    * Constructor that builds the configuration environment for this connector
    * according to the given profile.
@@ -61,17 +75,15 @@ public class MOASoapWithAttachmentConnector implements Connector
    * parameters defined in the configuration are used.
    * </p>
    * 
-   * @param profile
-   *          The profile from which the Environment should be assembled.
-   * @throws SettingsException
-   *           f.e.
-   * @throws SignatureException
+   * @param connectorParameters
+   *          The parameters for this connector.
+   * @throws ConnectorException
    *           f.e.
    */
-  public MOASoapWithAttachmentConnector(String profile) throws ConnectorException
+  public MOASoapWithAttachmentConnector(ConnectorParameters connectorParameters) throws ConnectorException
   {
-	  
-    this.environment = new Environment(profile, MULTIPART_LOC_REF_CONTENT);
+    this.params = connectorParameters;
+    this.environment = new Environment(this.params.getProfileId(), MULTIPART_LOC_REF_CONTENT);
   }
 
   protected String prepareSignRequest(SignatureData data) throws ConnectorException
@@ -176,7 +188,7 @@ public class MOASoapWithAttachmentConnector implements Connector
     String xml_content = null;
     if (!SigKZIDHelper.isMOASigned(so))
     {
-      DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.environment.getProfile(), "not needed here");
+      DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here");
       xml_content = bku_connector.prepareXMLContent(data, so);
     }
     else
@@ -187,12 +199,22 @@ public class MOASoapWithAttachmentConnector implements Connector
     String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
     verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
     verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl());
+    
+    String returnHashInputDataElement = "";
+    if (this.params.isReturnHashInputData())
+    {
+      returnHashInputDataElement = RETURN_HASH_INPUT_DATA;
+    }
+    verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement);
+    
+    verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime()));
+    
 
     log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
 
     return verify_request_xml;
   }
-
+  
   /**
    * Analyzes the verify response string.
    * 
@@ -297,20 +319,20 @@ public class MOASoapWithAttachmentConnector implements Connector
     try
     {
 	    // for performance measurement
-	    long startTime = 0; 
-	    if (log.isInfoEnabled()) {
-	    	startTime = System.currentTimeMillis();    	
-	    }
+//	    long startTime = 0; 
+//	    if (log.isInfoEnabled()) {
+//	    	startTime = System.currentTimeMillis();    	
+//	    }
     	
 //      Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
       Properties response_properties = MOASoapConnection.doPostRequestMultipart(url,mode, request_string, data );
       
       // for performance measurement
-      if (log.isInfoEnabled()) {
-      	long endTime = System.currentTimeMillis();
-      	String toReport = "MOA-PROCESSING;-;-;" + (endTime - startTime) + ";"; 
-      	log.info(toReport);
-      }
+//      if (log.isInfoEnabled()) {
+//      	long endTime = System.currentTimeMillis();
+//      	String toReport = "MOA-PROCESSING;-;-;" + (endTime - startTime) + ";"; 
+//      	log.info(toReport);
+//      }
       
       return response_properties;
     }
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java
index ed4fc7a..01e60fa 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java
@@ -188,8 +188,23 @@ public class DataURLServlet extends HttpServlet
         si.outputAvailable = true;
       }
 
-      SignServletHelper.returnSignResponse(si, response);
-
+      if (si.output.getMimeType().equals("text/xml") && si.outputAvailable)
+      {
+        // For "detached" signatures, the return value (data sink) is the response xml,
+        // but when passed through the BKU it is interpreted as another request
+        // which will generate a return code 1501
+        // Then PDF-AS would answer with the response as well generating
+        // another 1501 and so forth.
+        // Therefor return it as TXT.
+        response.setContentType("text/plain");
+        response.setCharacterEncoding("UTF-8");
+        response.getWriter().println("Das detached XML kann nicht direkt durch die BKU geschliffen werden, weil diese es als Request interpretieren w�rde. Daher das XML als Text:");
+        response.getWriter().println(si.si.getSignSignatureObject().response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY));
+      }
+      else
+      {
+        SignServletHelper.returnSignResponse(si, response);
+      }
     }
   }
   
-- 
cgit v1.2.3