Commits

Christian Schlichtherle committed 2982d98 Merge

Merged.

Comments (0)

Files changed (14)

             <dependency>
                 <groupId>com.fasterxml.jackson.module</groupId>
                 <artifactId>jackson-module-jaxb-annotations</artifactId>
-                <version>2.2.0</version>
+                <version>2.2.1</version>
             </dependency>
             <dependency>
                 <groupId>commons-codec</groupId>

src/site/apt/certification.apt.vm

+    -----------------------
+    Certification Process
+    -----------------------
+    Christian Schlichtherle
+    -----------------------
+
+Certification Process
+
+    First, <<thank you very much for buying into a commercial license agreement
+    for TrueLicense!>>
+
+    To complete your order, we need to cooperate in order to generate a trusted
+    certificate entry in the keystore which is embedded in your product so that
+    it can successfully verify license keys.
+    Don't panic - it's quite simple.
+    This section walks you through the process.
+
+* Prerequisites
+
+    First, you need to have a license vendor application alias key generator
+    ready for your product.
+
+    In case you haven't already done so, please follow the documentation of the
+    {{{./truelicense-maven-archetype/index.html}TrueLicense Maven Archetype}}
+    in order to generate a sample project for you.
+    If you have already done this, mind you that you must follow the
+    instructions to
+    {{{./truelicense-maven-archetype/customizing.html}customize}}
+    the generated keys and passwords of the sample project.
+    <<REUSING THE GENERATED KEYS AND PASSWORDS AS IS COMPLETELY VOIDS THE
+    PROTECTION OF YOUR PRODUCT!>>
+
+* Issuing the Certificate Signing Request
+
+    Next, you need to issue a Certificate Signing Request (CSR).
+    Change to the directory with the keystore for the license vendor
+    application.
+    If you generated this from the TrueLicense Maven Archetype, this would look
+    like:
+
++--
+$ cd $SAMPLE/keygen
++--
+
+    Then submit the following command:
+
++--
+$ keytool -certreq -keystore src/main/resources/private.ks -storetype jceks
++--
+
+    Once you've entered the password for the keystore and the entry, you should
+    see some output like this:
+
++--
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICnDCCAYQCAQAwJzElMCMGA1UEAxMcVHJ1ZUxpY2Vuc2UgMiBTYW1wbGUgUHJvamVjdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI/j1yvXjrHJOZRDj3fmAygwfevaqoBjBfok+JDV
+QTA5Mc60wxWMbOlsQhkdldPXemgpA7UoQRDN/KlOAnDHyjN66RBRVeEe561itYtFBfTBXrnuEoAP
+1WPEcDwmS/1uzGLak//PoP/WTE3E4mVAzXJYDiAx7gRL/+k3UiyDKObzZ8ZUSMrd0UvZp/zNxBF/
+a26dGlKPXJGPGkO7E7eTgMS6yh4UhCoD6iBufCL8cmmfMT+PkdJHA3+h0cYw7ptqcbFQ22sHgWZ5
+VTl54ZeHZMdC8cufT28nxJ11L1y56bI5cbXdEzMYlkJTMnXTlhw+VQntMOhbTOO6ziKHaRH6R4MC
+AwEAAaAwMC4GCSqGSIb3DQEJDjEhMB8wHQYDVR0OBBYEFF4Y7LLAhuFIljvLTT5dAHhDIH1WMA0G
+CSqGSIb3DQEBCwUAA4IBAQBxTspAnDoefC71uoCQXnWjpvrfDPzfnSV7RqaIZoGx7IHVzB6mlMpJ
+2OI/O8mxvsem2hMvX8EeIG/SDOEDkbawq7XflMcfXAguRGHB/t2y8XaN+VayyAhAB/erY9mHF/rd
+1md4levKcPUywMpIUWCxkoZyjTXD6U+KcKJaajGnvcHNLsmopl6eIWkksTIlO5B1KJc64NtI0Dl6
+ycKY7knnl1V53euX59yhfz3og4vjlQNOSet9uFe0Q2MRY06NVi1uzv9E9rMv0srd18amjB5m8EdC
+z5UXVCwHhByE5MCTFs6TdlPZ2tHNUfNNet/clDpfJ2SI/KE8u7Skn9vqHdgr
+-----END NEW CERTIFICATE REQUEST-----
++--
+
+    Copy-paste this into an email and send it to sales AT schlichtherle DOT de.
+
+    Don't worry about security, the CSR just contains your public key, not your
+    private key, so there is no confidential data in it.
+    Actually, you can decode the information in this request if you copy-paste
+    it into the following command:
+
++--
+$ keytool -printcertreq -v
++--
+
+##
+## For processing the CSR, first decode its information as shown above.
+## Check the distinguished name of the subject - it should NOT read
+## "CN=TrueLicense 2 Sample Project".
+## Otherwise, the sample project hasn't been properly customized.
+##
+## If the public key in the CSR is an X.509 Format RSA Key,
+## then copy-paste the CSR into the following command:
+##
+## +--
+## $ keytool -gencert -alias truelicense2-rsa -rfc -validity 365
+## +--
+##
+## Otherwise, if the public key is an X.509 Format DSA Key,
+## then copy-paste the CSR into the following command:
+##
+## +--
+## $ keytool -gencert -alias truelicense2-dsa -rfc -validity 365
+## +--
+##
+## Note the different private key entries for RSA and DSA keys.
+## The validity is not used now, but maybe required for future use.
+## For now it's just a courtesy which enables recipients to track their
+## subscription.
+## Finally, copy-paste the output into the response email.
+##
+
+* Validating the Certificate Response
+
+    Next, you will get an email with the Certificate Response (CR) in the
+    message body which looks like this:
+
++--
+----BEGIN CERTIFICATE-----
+...
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+...
+-----END CERTIFICATE-----
++--
+
+    Although not strictly required, it's generally recommended to decode the
+    information in the CSR by copy-pasting it into the following command:
+
++--
+$ keytool -printcert -v
++--
+
+    Note that the response contains two certificates.
+    The first certificate contains your public key and is signed by the
+    X.500 principal with the distinguished name
+    <<<CN=TrueLicense 2, O=Schlichtherle IT Services>>>.
+
+    The second certificate contains the public key for signing the first
+    certificate and is signed by the X.500 principal with the distinguished
+    name
+    <<<CN=Schlichtherle IT Services, OU=Schlichtherle IT Services, O=Schlichtherle IT Services, L=Berlin, ST=Berlin, C=DE>>>.
+
+    Because the second certificate is signed with a self-signed certificate,
+    you should check that its serial number and SHA-256 fingerprint match one
+    of the following two entries:
+
+*--+--+--+
+||Key Algorithm||Serial Number||SHA-256 fingerprint||
+*--+--+--+
+|RSA|<<<ac44e3d>>>|<<<E1:51:B1:96:6F:79:67:D3:BA:56:D4:B1:D4:F0:D0:12:D5:22:C7:9A:64:2C:DA:77:87:3F:93:91:85:BD:8F:E5>>>|
+*--+--+--+
+|DSA|<<<76dbe28c>>>|<<<21:B0:86:6F:E6:DE:9E:DA:A2:E9:50:8B:07:CE:B5:E6:12:87:C7:B6:4D:89:A9:C7:40:B8:63:F7:DB:7D:EB:AA>>>|
+*--+--+--+
+
+    You need to confirm this when importing the CSR later.
+
+* Importing the Certificate Response into the License Vendor Application
+
+    Next, although this is not strictly required, you should import the
+    CR into the key generator for future reference.
+
+    Change the current directory to the license vendor application again and
+    submit the following command:
+
++--
+$ keytool -importcert -keystore src/main/resources/private.ks -storetype jceks
++--
+
+    Because the second certificate is self-signed, you need to confirm to trust
+    it - see above.
+
+    Now the private key store of the license vendor application contains a
+    private key entry with a private/public key pair which has been signed
+    by TrueLicense 2.
+
+* Importing the Certificate Response into the License Consumer Application
+
+    Next, you need to import the CR into your product so that it can
+    successfully verify license keys.
+
+    Change the current directory to the license consumer application.
+    If you generated this from the TrueLicense Maven Archetype, this would look
+    like:
+
++--
+$ cd $SAMPLE/keymgr
++--
+
+    Then submit the following command:
+
++--
+$ keytool -importcert -keystore src/main/resources/public.ks -storetype jceks
++--
+
+    Now the public key store of the license consumer application contains a
+    trusted certificate key entry with a public key pair which has been signed
+    by TrueLicense 2.
+    <<You are finally ready to create and sell license keys - congratulations!>>

src/site/apt/index.apt.vm

           GNU&#160;AFFERO&#160;GENERAL&#160;PUBLIC&#160;LICENSE, Version&#160;3
           ({{{http://www.gnu.org/licenses/agpl-3.0.html}AGPLv3}}).
           In this case, you need to license your software under the same terms!
-          At runtime, TrueLicense issues a notice telling your users that your
+          At runtime, TrueLicense logs a notice telling your users that your
           software is subject to the AGPLv3 and that they need to have access
           to its source code for free.
 
     [[1]] For closed source software, you need to buy into a commercial license
           agreement.
-          In this case, you will get one or more digital signed certificates in
-          return for your payment - see below.
-          At runtime, if the signatures are found to be valid then no notice
-          gets issued.
+          In this case, you will get a set of certificates in return for your
+          payment - see below.
+          At runtime, if the signature of each certificate is found to be
+          valid then no notice gets logged.
 
-##    For more information, please refer to
-##    {{{./dual-license-explained.html}Dual License Explained}}.
+    []
 
 * Price
 
-    The price for a commercial license is 299&#160;EUR per licensable feature
-    set per software product per annum.
-    Many products have only one feature set which includes all features;
-    the effective price is then 299&#160;EUR per annum.
+    The price for a commercial license agreement is
+    <<299&#160;EUR per certificate per product per annum>>
+    (plus VAT if applicable).
+    Each certificate is used to unlock access to a particular set of product
+    features.
+    For example, many products need only one certificate in order to unlock
+    access to all their features.
+    In this case, the effective price is just 299&#160;EUR per annum.
 
-    For each feature set, you get a digitally signed certificate.
-    The certificate signs a public key which is pre-generated by you.
-    TrueLicense verifies the signature of the certificate and uses its public
-    key to verify the license keys for the associated feature set.
+* Term
+
+    The commercial license agreement stays in effect as long as your product
+    is available for sale.
+    Once your product has gone out of sale, you can terminate the agreement
+    without notice.
+    However, no refunds are paid.
+
+* Ordering
 
     For ordering please contact sales AT schlichtherle DOT de.
-    Please include your billing details, the product name and its number of
-    feature sets.
-    Wire transfer only - no credit cards accepted.
+    Please include your billing details, the name of your product and the
+    number of certificates.
+    I accept PayPal and wire transfer - no credit cards please.
+    Once payed, I'll walk you through the simple certification process.

src/site/apt/prerequisites.apt.vm

 
     To use TrueLicense, you need
     {{{http://www.oracle.com/technetwork/java/javase/downloads/index.html}Java Standard Edition 6}}
-    (JSE6) or later.
-    TrueLicense runs fine with JSE7.
+    (JSE 6) or later.
 
     To use the TrueLicense Maven Plugin and the TrueLicense Maven Archetype,
     you need {{{http://maven.apache.org/download.cgi}Apache Maven 3.0.4}} or

truelicense-core/src/main/java/net/java/truelicense/core/auth/BasicRepository.java

         engine.update(artifactData);
         final byte[] signatureData = engine.sign();
 
-        final String artifactBody = body(codec, artifactData);
-        final String signatureBody = encode(signatureData);
-        final String algorithm = engine.getAlgorithm();
+        final String encodedArtifact = body(codec, artifactData);
+        final String encodedSignature = encode(signatureData);
+        final String signatureAlgorithm = engine.getAlgorithm();
         final Artifactory artifactory = new EncodedArtifact(codec, store);
 
         final RepositoryModel model = model();
-        model.setArtifact(artifactBody);
-        model.setSignature(signatureBody);
-        model.setAlgorithm(algorithm);
+        model.setArtifact(encodedArtifact);
+        model.setSignature(encodedSignature);
+        model.setAlgorithm(signatureAlgorithm);
 
         return artifactory;
     }

truelicense-core/src/main/java/net/java/truelicense/core/auth/RepositoryModel.java

 import net.java.truelicense.core.util.*;
 
 /**
- * A model for storing authenticated objects (artifacts).
+ * A model for storing authenticated objects (artifacts) as encoded strings.
+ * The content type and the content transfer encoding of the encoded artifact
+ * and encoded signature are defined externally.
+ * <p>
  * This class is used by {@linkplain Repository repositories} to store
  * artifacts for {@linkplain Repository#sign signing} and
  * {@linkplain Repository#verify verifying}.
 
     private String artifact, signature, algorithm;
 
+    /** Returns the encoded artifact. */
     @XmlElement(required = true)
     public final String getArtifact() { return artifact; }
 
-    public final void setArtifact(final String body) {
-        this.artifact = body;
+    /** Sets the encoded artifact. */
+    public final void setArtifact(final String encodedArtifact) {
+        this.artifact = encodedArtifact;
     }
 
+    /** Returns the encoded signature. */
     @XmlElement(required = true)
     public final String getSignature() { return signature; }
 
-    /**
-     * Sets the signature body.
-     * The assumed signature type is {@code application/octet-stream} and its
-     * transfer encoding is {@code base64}.
-     *
-     * @param body the signature body.
-     */
-    public void setSignature(final String body) {
-        this.signature = body;
+    /** Sets the encoded signature. */
+    public void setSignature(final String encodedSignature) {
+        this.signature = encodedSignature;
     }
 
+    /** Returns the signature algorithm. */
     @XmlElement(required = true)
-    public final String getAlgorithm()  { return algorithm; }
+    public final String getAlgorithm() { return algorithm; }
 
-    public final void setAlgorithm(final String algorithm) {
-        this.algorithm = algorithm;
+    /** Sets the signature algorithm. */
+    public final void setAlgorithm(final String signatureAlgorithm) {
+        this.algorithm = signatureAlgorithm;
     }
 
+    /**
+     * Returns {@code true} if and only if the given object is an instance of
+     * {@code RepositoryModel} and it's encoded artifact, encoded signature and
+     * signature algorithm compare equal, whereby the case of the signature
+     * algorithm is ignored.
+     */
     @Override
     @SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")
     public boolean equals(final Object obj) {
         if (this == obj) return true;
         if (!(obj instanceof RepositoryModel)) return false;
         final RepositoryModel that = (RepositoryModel) obj;
-        return  Objects.equals(this.signature, that.signature) &&
+        return  Objects.equals(this.artifact, that.artifact) &&
+                Objects.equals(this.signature, that.signature) &&
                 Strings.equalsIgnoreCase(this.algorithm, that.algorithm);
     }
 
+    /** Returns a hash code which is consistent with {@link #equals}. */
     @Override
     public int hashCode() {
         int c = 17;
+        c = 31 * c + Objects.hashCode(artifact);
         c = 31 * c + Objects.hashCode(signature);
         c = 31 * c + Objects.hashCode(Strings.toLowerCase(algorithm, ROOT));
         return c;

truelicense-maven-archetype/src/main/resources/archetype-resources/keygen/src/main/java/keygen/Main.java

             final License ol = manager.create(il, s);
             err.println(ol);
             final String olp = o.get(CreateOption.OUTPUT); // <output-license-path>
-            if (null != olp) c.encode("-".equals(olp)
-                    ? Sinks.output()
-                    : context.fileStore(new File(olp)),
-                    ol);
+            if (null != olp)
+                c.encode("-".equals(olp)
+                        ? Sinks.output()
+                        : context.fileStore(new File(olp)),
+                        ol);
         }
     },
 

truelicense-maven-archetype/src/main/resources/archetype-resources/keygen/src/test/java/keygen/MainIT.java

         return folder.newFile(name);
     }
 
-    private static byte[] read(File file) throws IOException {
+    private static byte[] read(final File file) throws IOException {
         final byte[] data = new byte[(int) file.length()];
         final InputStream in = new FileInputStream(file);
         try { new DataInputStream(in).readFully(data); }

truelicense-maven-archetype/src/main/resources/archetype-resources/pom.xml

 
         <truelicense.version>${truelicense-version}</truelicense.version>
 
-        <jackson.version>2.2.0</jackson.version>
+        <jackson.version>2.2.1</jackson.version>
 
         <jersey.version>1.17.1</jersey.version>
     </properties>
                 </plugin>
                 <plugin>
                     <artifactId>maven-project-info-reports-plugin</artifactId>
-                    <version>2.6</version>
+                    <version>2.7</version>
                 </plugin>
                 <plugin>
                     <artifactId>maven-release-plugin</artifactId>
                 </plugin>
                 <plugin>
                     <artifactId>maven-site-plugin</artifactId>
-                    <version>3.1</version>
+                    <version>3.3</version>
                 </plugin>
                 <plugin>
                     <artifactId>maven-source-plugin</artifactId>

truelicense-maven-archetype/src/site/apt/customizing.apt.vm

 
     []
 
-    Note that you must follow the instructions in this section to change the
+    Note that you must follow the instructions in this section to customize the
     generated keys and passwords of the sample project.
     <<REUSING THE GENERATED KEYS AND PASSWORDS AS IS COMPLETELY VOIDS THE
     PROTECTION OF YOUR PRODUCT!>>
     -keyalg rsa
 +--
 
-    The <<<keytool>>> command creates a private key entry for the digital
-    signature algorithm <<<SHA256withRSA>>> in a key store of the type
+    The <<<keytool>>> command creates a private key entry signed with the
+    digital signature algorithm <<<SHA256withRSA>>> in a key store of the type
     <<<JCEKS>>>.
     These are good choices to achieve a strong security level while maintaining
     compatibility with any JSE 6 compliant platform.
     You can safely reuse the password for the private key store of the KeyGen
     module - see above.
 
-    You may notice that you are not prompted for a password to protect the
-    entry in the key store.
+    Note that you are not prompted for a password to protect the entry in the
+    key store.
     This is because the entry only contains a public key and no private key.
 
 ** Recreating the Private/Public Key Pair for FTP License Keys

truelicense-maven-archetype/src/site/apt/generating.apt.vm

 
 Generating a Sample Project
 
-    To generate a sample project, type the following command in a shell,
-    thereby customizing the property values to meet your requirements:
+    To generate a sample project, copy-paste the following command into a shell
+    - without the leading dollar sign.
+    Before you press the Enter key, please customize the property values to
+    meet your requirements:
 
 +--
 $ mvn archetype:generate \
     -DarchetypeArtifactId=${project.artifactId} \
     -DarchetypeVersion=${project.version} \
     -DgroupId=com.company \
-    -DartifactId=sample \
+    -DartifactId=product \
     -Dversion=0.1-SNAPSHOT \
-    -Dpackage=com.company
+    -Dpackage=com.company \
+    -Dsubject="Product 1"
 +--
 
-    The following table explains all available properties:
+    The following table explains the customizable properties:
 
 *--+--+--+
-||Name||Description||Default Value||
+|| Name || Default Value || Description
 *--+--+--+
-|<<<groupId>>>|n/a|The group ID of the generated project.
+|<<<groupId>>> | n/a | The group ID of the generated project. This could be the reversed domain name for your company - see below.
 *--+--+--+
-|<<<artifactId>>>|n/a|The artifact ID of the parent POM of the generated project.
+|<<<artifactId>>> | n/a | The artifact ID of the parent POM for the generated project. This could be your product name. Whatever it is, it should be converted to lowercase - see below.
 *--+--+--+
-|<<<version>>>|n/a|The version of the generated project.
+|<<<version>>> | n/a | The version of the generated project. This could be your product version. Please specify at most two dots and append "-SNAPSHOT" to it - see below.
 *--+--+--+
-|<<<package>>>|n/a|The base package name of the generated project.
+|<<<package>>> | n/a | The base package name of the generated project. This should be the same as the group ID if it's a valid package name.
 *--+--+--+
-|<<<truelicense-version>>>|<<<${project.version}>>>|The version of the TrueLicense library. You can change this property by editing the generated parent POM - see {{{./customizing.html}Customizing the Sample Project}}.
+|<<<subject>>> | <<<Product 1>>> | The licensing subject for validation. This should include the name of your product and a version number range. You can change this property by editing the generated licensing schema in the KeyGen and KeyMgr modules - see {{{./customizing.html}Customizing the Sample Project}}.
 *--+--+--+
-|<<<subject>>>|<<<Product 1>>>|The licensing subject for validation. This should include the name of your product and a version number range. You can change this property by editing the generated licensing schema in the KeyGen and KeyMgr modules - see {{{./customizing.html}Customizing the Sample Project}}.
-*--+--+--+
-|<<<secret-ftp-marker-class>>>|<<<sun.security.provider.Sun>>>|The name of the secret class which is used as a marker for checking the consumer's eligibility for a Free Trial Period (FTP). You can change this property or disable the feature by editing the generated licensing schema in the KeyMgr module - see {{{./customizing.html}Customizing the Sample Project}}.
+|<<<secret-ftp-marker-class>>> | <<<sun.security.provider.Sun>>> | The name of the secret class which is used as a marker for checking the license consumer's eligibility for a Free Trial Period (FTP). You can change this property or disable the feature by editing the generated licensing schema in the KeyMgr module - see {{{./customizing.html}Customizing the Sample Project}}.
 *--+--+--+
 
-    Upon successful execution, a new directory with the value of the property
-    <<<artifactId>>> as its name will have been created in the current
-    directory.
+    For explanation of the <<<groupId>>>, <<<artifactId>>> and <<<version>>>
+    properties, please check
+    {{http://maven.apache.org/pom.html#Maven_Coordinates}}.
+
+    Upon successful execution, a new directory with the artifact ID as its name
+    will have been created in the current directory.
     From now on, the absolute path of the generated sample directory gets
     referenced by the expression <<<$SAMPLE>>>.
 

truelicense-maven-archetype/src/test/filtered/projects/basic/archetype.properties

 groupId=com.company
-artifactId=sample
+artifactId=product
 version=0.1-SNAPSHOT
 package=com.company
 truelicense-version=${project.version}

truelicense-swing/src/main/java/net/java/truelicense/swing/nexes/Wizard.java

      * Indicates that the 'Finish' button was pressed to close the dialog.
      */
     public static final int FINISH_RETURN_CODE = 0;
+
     /**
      * Indicates that the 'Cancel' button was pressed to close the dialog.
      */
     public static final int CANCEL_RETURN_CODE = 1;
+
     /**
      * Indicates that the dialog closed due to an internal error.
      */
     public static final int ERROR_RETURN_CODE = 2;
+
     /**
      * The String-based action command for the 'Next' button.
      */
     public static final String NEXT_BUTTON_ACTION_COMMAND
             = "NextButtonActionCommand"; // NOI18N
+
     /**
      * The String-based action command for the 'Back' button.
      */
     public static final String BACK_BUTTON_ACTION_COMMAND
             = "BackButtonActionCommand"; // NOI18N
+
     /**
      * The String-based action command for the 'Cancel' button.
      */
     public static final String CANCEL_BUTTON_ACTION_COMMAND
             = "CancelButtonActionCommand"; // NOI18N
+
     /**
      * The default text used for the 'Back' button. Good candidate for i18n.
      */
     public static final String DEFAULT_BACK_BUTTON_TEXT
             = message("backButton").toString();
+
     /**
      * The default text used for the 'Next' button. Good candidate for i18n.
      */
     public static final String DEFAULT_NEXT_BUTTON_TEXT
             = message("nextButton").toString();
+
     /**
      * The default text used for the 'Finish' button. Good candidate for i18n.
      */
     public static final String DEFAULT_FINISH_BUTTON_TEXT
             = message("finishButton").toString();
+
     /**
      * The default text used for the 'Cancel' button. Good candidate for i18n.
      */

truelicense-swing/src/main/java/net/java/truelicense/swing/nexes/WizardPanelDescriptor.java

      */
     public @CheckForNull String getNextPanelIdentifier() { return null; }
 
-    /**
-     * Returns to java.awt.Component that serves as the actual panel.
-     *
-     * @return A reference to the java.awt.Component that serves as the panel
-     */
+    /** Returns the actual panel. */
     public JPanel getPanel() { return panel; }
 
+    /** Returns the wizard. */
+    public Wizard getWizard() { return wizard; }
+
     void setWizard(final Wizard wizard) {
         assert null != wizard;
         this.wizard = wizard;
     }
 
-    /**
-     * Returns the wizard.
-     */
-    public Wizard getWizard() { return wizard; }
-
-    /**
-     * Returns the model of the wizard.
-     */
+    /** Returns the model of the wizard. */
     public WizardModel getWizardModel() { return wizard.getModel(); }
 
     /**