/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors. 
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.test.security.vault;

import org.jboss.security.Util;
import org.jboss.security.plugins.PBEUtils;
import org.jboss.security.vault.SecurityVault;
import org.jboss.security.vault.SecurityVaultException;
import org.jboss.security.vault.SecurityVaultFactory;
import org.jboss.security.vault.SecurityVaultUtil;
import org.jboss.test.SecurityActions;
import org.junit.Assume;
import org.junit.Test;
import org.picketbox.plugins.vault.PicketBoxSecurityVault;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.*;

/**
 * Unit Test the {@link SecurityVault} Implementation
 * 
 * Note: replacement-vault.keystore has been created using: 
 *       keytool -genkey -alias mykey -keystore replacement-vault.keystore -keyalg RSA -keysize 1024 -storepass supersecret11 -keypass supersecret11 -dname "CN=Picketbox vault,OU=picketbox,O=JBoss"
 *       
 * @author Anil.Saldhana@redhat.com
 * @since Aug 12, 2011
 */
public class SecurityVaultUnitTestCase
{ 
   //String dataDir = "${java.io.tmpdir}/enc/";
   
   @Test
   public void testDefaultVault() throws Exception
   {
      SecurityVault vault = SecurityVaultFactory.get();
      assertNotNull(vault);
      assertTrue(vault instanceof PicketBoxSecurityVault);
      assertFalse(vault.isInitialized());
   }

   @Test
   public void testClassLoaderVault() throws Exception
   {
      //Back up the existing vault and reset it
      Field field = SecurityVaultFactory.class.getDeclaredField("vault");
      field.setAccessible(true);
      Object existingVault = field.get(null);
      try
      {
         field.set(null, null);
         ClassLoader cl = SecurityVaultFactory.class.getClassLoader();
         SecurityVault vault = SecurityVaultFactory.get(cl, TestVault.class.getName());
         assertNotNull(vault);
         assertTrue(vault instanceof TestVault);
         assertFalse(vault.isInitialized());
      }
      finally
      {
         if (existingVault != null)
         {
            field.set(null, existingVault);
         }
      }
   }
   
   @Test
   public void testHandshake() throws Exception
   {
      
      setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault1/vault.jks", 
            "src/test/resources/keystore/vault_data", "target/vaults/vault1/vault_data");
      
      SecurityVault vault = getNewSecurityVaultInstance(); 
      Map<String,Object> options = getVaultOptionsMap(
            "target/vaults/vault1/vault.jks", 
            "target/vaults/vault1/vault_data", 
            "vault", "12438567", 50, "vault22"); 
            
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      Map<String,Object> handshakeOptions = new HashMap<String,Object>();
      handshakeOptions.put(PicketBoxSecurityVault.PUBLIC_CERT,"vault");
      
      byte[] sharedKey = vault.handshake(handshakeOptions);
      assertNotNull(sharedKey);
   }
   
   @Test
   public void testHandshakeAnConversionForLongAlias() throws Exception
   {
      setInitialVaulConditions("src/test/resources/long_alias_keystore/vault.jks", "target/vaults/long_alias_keystore/vault.jks", 
            "src/test/resources/long_alias_keystore/vault_data", "target/vaults/long_alias_keystore/vault_data");
      
      SecurityVault vault = getNewSecurityVaultInstance(); 
      Map<String,Object> options = getVaultOptionsMap(
            "target/vaults/long_alias_keystore/vault.jks", 
            "target/vaults/long_alias_keystore/vault_data", 
            "superverylongvaultname", "87654321", 23, "password1234", Boolean.TRUE);

      vault.init(options);
      assertTrue("Vault is supposed to be inicialized", vault.isInitialized());
      
      Map<String,Object> handshakeOptions = new HashMap<String,Object>();
      byte[] sharedKey = vault.handshake(handshakeOptions);
      assertNotNull(sharedKey);

      // not relevant anymore, but leaving it as is 
      boolean containsLineBreaks = false;
      for (byte b: sharedKey) {
         if (b == '\n') {
            containsLineBreaks = true;
            break;
         }
      }
      assertFalse("Shared key returned from hadshake cannot contain line break character", containsLineBreaks);
   }

   
   @Test
   public void testMaskedPasswordFallback() throws Exception {

      setInitialVaulConditions(
              "src/test/resources/vault-fallback/vault-fallback.keystore", "target/vaults/vault-fallback/vault-fallback.keystore", 
              "src/test/resources/vault-fallback/vault_data", "target/vaults/vault-fallback/vault_data");
      
      // see src/test/resources/vault-fallback/readme.txt
      // this test uses wrongly generated maked password value and should fallback to correct one 
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-fallback/vault-fallback.keystore", 
            "target/vaults/vault-fallback/vault_data", 
            "valias", "bdfbdf12", 12, "MASK-UWB5tlhOmKYzJVl9KZaPN");
      
      SecurityVault vault = getNewSecurityVaultInstance();
      assertFalse(vault.isInitialized());
      
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      vault.handshake(null);
      
      // let's try to check if proper values are stored in the vault
      assertSecretValue(vault, "vblock", "attr1", "secret1");
      
   }
   
   @Test
   public void testStoreAndRetrieve() throws Exception
   {

      setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault2/vault.jks", 
            "src/test/resources/keystore/vault_data", "target/vaults/vault2/vault_data");
      
      Map<String,Object> options = getVaultOptionsMap(
            "target/vaults/vault2/vault.jks", 
            "target/vaults/vault2/vault_data", 
            "vault", "12438567", 50, "vault22"); 

      String vaultBlock = "SecBean";
      String attributeName = "theAttribute";
      
      char[] attributeValue = "someValue".toCharArray();
      
      SecurityVault vault = getNewSecurityVaultInstance();

      vault.init(options);
      assertTrue(vault.isInitialized());
      
      Map<String,Object> handshakeOptions = new HashMap<String,Object>();
      
      byte[] sharedKey = vault.handshake(handshakeOptions);
      assertNotNull(sharedKey);
      
      vault.store(vaultBlock, attributeName, attributeValue , sharedKey);
      
      assertTrue(vault.exists(vaultBlock, attributeName));
      //Now retrieve 
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock, attributeName, sharedKey))); 
      
      vault.store(vaultBlock+"1", attributeName+"2", attributeValue , sharedKey);
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock+"1", attributeName+"2", sharedKey))); 
      
      System.out.println("Currently storing:" + vault.keyList());
      
      assertTrue(vault.remove(vaultBlock+"1", attributeName+"2", sharedKey));
      assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
   }
   
   @Test
   public void testClassBasedKeystorePassword() throws Exception
   {

      setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault2/vault.jks",
            "src/test/resources/keystore/vault_data", "target/vaults/vault2/vault_data");

      Map<String,Object> options = getVaultOptionsMap(
            "target/vaults/vault2/vault.jks",
            "target/vaults/vault2/vault_data",
            "vault", "12438567", 50, "{CLASS}org.jboss.test.security.vault.KeystorePasswordProvider");

      String vaultBlock = "aBlock";
      String attributeName = "anAttribute";

      char[] attributeValue = "aValue".toCharArray();

      SecurityVault vault = getNewSecurityVaultInstance();

      vault.init(options);
      assertTrue(vault.isInitialized());

      Map<String,Object> handshakeOptions = new HashMap<String,Object>();

      byte[] sharedKey = vault.handshake(handshakeOptions);
      assertNotNull(sharedKey);

      vault.store(vaultBlock, attributeName, attributeValue , sharedKey);

      assertTrue(vault.exists(vaultBlock, attributeName));
      //Now retrieve
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock, attributeName, sharedKey)));

      vault.store(vaultBlock+"1", attributeName+"2", attributeValue, sharedKey);
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock+"1", attributeName+"2", sharedKey)));

      System.out.println("Currently storing:" + vault.keyList());

      assertTrue(vault.remove(vaultBlock+"1", attributeName+"2", sharedKey));
      assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
   }

   @Test
   public void testExtCmdBasedKeystorePassword() throws Exception
   {
      // since this test uses an external BASH script it is valid for Linux systems only
      String OS_NAME = SecurityActions.getProperty("os.name", null);
      Assume.assumeTrue(OS_NAME.startsWith("Linux") || OS_NAME.startsWith("LINUX"));

      setInitialVaulConditions("src/test/resources/keystore/vault.jks", "target/vaults/vault2/vault.jks",
            "src/test/resources/keystore/vault_data", "target/vaults/vault2/vault_data");

      String absolutePathToAskPass = SecurityVaultUnitTestCase.class.getResource("/bin/askpass.sh").getFile();
      System.out.println("absolutePathToAskPass: " + absolutePathToAskPass);

      // 'Enter passphrase for *' is hard-coded into kwalletaskpass for example
      Map<String,Object> options = getVaultOptionsMap(
            "target/vaults/vault2/vault.jks",
            "target/vaults/vault2/vault_data",
            "vault", "12438567", 50, "{CMD}/bin/sh," + absolutePathToAskPass + ",Enter passphrase for askpass test");

      String vaultBlock = "aBlock";
      String attributeName = "anAttribute";

      char[] attributeValue = "aValue".toCharArray();

      SecurityVault vault = getNewSecurityVaultInstance();

      vault.init(options);
      assertTrue(vault.isInitialized());

      Map<String,Object> handshakeOptions = new HashMap<String,Object>();

      byte[] sharedKey = vault.handshake(handshakeOptions);
      assertNotNull(sharedKey);

      vault.store(vaultBlock, attributeName, attributeValue , sharedKey);

      assertTrue(vault.exists(vaultBlock, attributeName));
      //Now retrieve
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock, attributeName, sharedKey)));

      vault.store(vaultBlock+"1", attributeName+"2", attributeValue, sharedKey);
      assertEquals(new String(attributeValue), new String(vault.retrieve(vaultBlock+"1", attributeName+"2", sharedKey)));

      System.out.println("Currently storing:" + vault.keyList());

      assertTrue(vault.remove(vaultBlock+"1", attributeName+"2", sharedKey));
      assertFalse(vault.exists(vaultBlock+"1", attributeName+"2"));
   }

   /**
    * See src/test/resources/vault-v0/readme.txt for initial vault setup (including secured attributes).
    * @throws Exception
    */
   @Test
   public void testConversion() throws Exception {

      setInitialVaulConditions("src/test/resources/vault-v0/vault-jks.keystore", "target/vaults/vault-v0/vault-jks.keystore", 
            "src/test/resources/vault-v0/vault_data", "target/vaults/vault-v0/vault_data");
      
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-v0/vault-jks.keystore", 
            "target/vaults/vault-v0/vault_data", 
            "thealias", "24681359", 88, "secretsecret");
      
      SecurityVault vault = getNewSecurityVaultInstance(); 

      // init should do the automatic conversion
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      byte[] sharedKey = vault.handshake(null);
      assertNotNull(sharedKey);
      
      // let's try to check if the converted vault contains all secret attributes from initial vault
      assertSecretValue(vault, "vb", "attr1", "pwd1");
      assertSecretValue(vault, "vb", "attr2", "pwd2");
      assertSecretValue(vault, "vb1", "attr1", "pwd3");
      assertSecretValue(vault, "vb2", "attr2", "pwd4");
      assertSecretValue(vault, "vb2", "attr3", "pwd5");
      assertSecretValue(vault, "vb", "attr3", "pwd6");
      
      
      // get new instance of vault to simulate restart of application server 
      SecurityVault convertedVault = getNewSecurityVaultInstance();
      assertFalse(convertedVault.isInitialized());
      convertedVault.init(options);
      assertTrue(convertedVault.isInitialized());

      convertedVault.handshake(null);
      
      // now try the same attributes on converted vault after restart
      assertSecretValue(convertedVault, "vb", "attr1", "pwd1");
      assertSecretValue(convertedVault, "vb", "attr2", "pwd2");
      assertSecretValue(convertedVault, "vb1", "attr1", "pwd3");
      assertSecretValue(convertedVault, "vb2", "attr2", "pwd4");
      assertSecretValue(convertedVault, "vb2", "attr3", "pwd5");
      assertSecretValue(convertedVault, "vb", "attr3", "pwd6");
      
   }
   
   @Test
   public void testVault_V1_open_retrieve() throws Exception {

      setInitialVaulConditions("src/test/resources/vault-v1/vault-jceks.keystore", "target/vaults/vault-v1/vault-jceks.keystore", 
            "src/test/resources/vault-v1/vault_data", "target/vaults/vault-v1/vault_data");
      
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-v1/vault-jceks.keystore", 
            "target/vaults/vault-v1/vault_data", 
            "test", "12345678", 34, "secretsecret");
      
      SecurityVault vault = getNewSecurityVaultInstance();
      assertFalse(vault.isInitialized());
      
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      vault.handshake(null);
      
      // let's try to check if proper values are stored in the vault
      assertSecretValue(vault, "vb1", "attr11", "secret11");
      assertSecretValue(vault, "vb1", "attr12", "secret12");
      
   }

   @Test(expected = SecurityVaultException.class)
   public void testVault_V1_open_wrong_alias() throws Exception {

      setInitialVaulConditions("src/test/resources/vault-v1/vault-jceks.keystore", "target/vaults/vault-v1-wrong/vault-jceks.keystore", 
            "src/test/resources/vault-v1/vault_data", "target/vaults/vault-v1-wrong/vault_data");
      
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-v1-wrong/vault-jceks.keystore", 
            "target/vaults/vault-v1-wrong/vault_data", 
            "thewrongalias", "12345678", 34, "secretsecret");
      
      SecurityVault vault = getNewSecurityVaultInstance();
      assertFalse(vault.isInitialized());
      
      vault.init(options);
      
   }

   @Test(expected = SecurityVaultException.class)
   public void testVaultWithReplacedKeystore() throws Exception {

      setInitialVaulConditions("src/test/resources/vault-v1/vault-replacement-jceks.keystore", "target/vaults/vault-v1/vault-jceks.keystore", 
            "src/test/resources/vault-v1/vault_data", "target/vaults/vault-v1/vault_data");
      
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-v1/vault-jceks.keystore", 
            "target/vaults/vault-v1/vault_data", 
            "test", "12345678", 34, "secretsecret");
      
      SecurityVault vault = getNewSecurityVaultInstance();
      assertFalse(vault.isInitialized());
      
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      vault.handshake(null);
      
      // let's try to check if the converted vault contains all secret attributes from initial vault
      assertSecretValue(vault, "vb1", "attr11", "secret11");
      assertSecretValue(vault, "vb1", "attr12", "secret12");
      
   }
   
   @Test
   public void testMoreSecretKeys() throws Exception {
      setInitialVaulConditions("src/test/resources/vault-v1-more/vault-jceks.keystore", "target/vaults/vault-v1-more/vault-jceks.keystore", 
            "src/test/resources/vault-v1-more/vault_data", "target/vaults/vault-v1-more/vault_data");
      
      final Map<String, Object> options = getVaultOptionsMap(
            "target/vaults/vault-v1-more/vault-jceks.keystore", 
            "target/vaults/vault-v1-more/vault_data", 
            "test", "12345678", 34, "secretsecret");
      
      SecurityVault vault = getNewSecurityVaultInstance();
      assertFalse(vault.isInitialized());
      
      vault.init(options);
      assertTrue(vault.isInitialized());
      
      vault.handshake(null);
      
      // let's try to check if proper values are stored in the vault
      assertSecretValue(vault, "vb1", "attr11", "secret11");
      assertSecretValue(vault, "vb1", "attr12", "secret12");
      
      final Map<String, Object> options2 = getVaultOptionsMap(
            "target/vaults/vault-v1-more/vault-jceks.keystore", 
            "target/vaults/vault-v1-more/vault_data", 
            "test2", "12345678", 34, "secretsecret");
      
      SecurityVault vault2 = getNewSecurityVaultInstance();
      assertFalse(vault2.isInitialized());
      
      vault2.init(options2);
      assertTrue(vault2.isInitialized());
      
      vault2.handshake(null);
      
      // let's try to check different alias can retrieve proper attribute
      assertSecretValue(vault2, "vb1", "attr13", "secret13");

      try {
         assertSecretValue(vault2, "vb1", "attr11", "secret11");
         fail("retrieving security attribute with different secret key alias has to fail.");
      }
      catch (SecurityVaultException e) {
         // deliberately empty
      }
      catch (Throwable e) {
         fail("unexpected exception " + e.getStackTrace().toString());
      }
      
      
   }
   
   @Test
   public void testUtil() throws Exception
   {
	   assertFalse(SecurityVaultUtil.isVaultFormat((String)null));
	   assertFalse(SecurityVaultUtil.isVaultFormat((char[])null));
   }
   
   private String getMaskedPassword(String pwd, String salt, int iterationCount) throws Exception
   {
      if (Util.isPasswordCommand(pwd))
         return pwd;

      if (pwd.startsWith(PicketBoxSecurityVault.PASS_MASK_PREFIX)) 
         return pwd;
      
      String algo = "PBEwithMD5andDES";
      
      // Create the PBE secret key 
      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES");

      char[] password = "somearbitrarycrazystringthatdoesnotmatter".toCharArray();
      PBEParameterSpec cipherSpec = new PBEParameterSpec(salt.getBytes(), iterationCount);
      PBEKeySpec keySpec = new PBEKeySpec(password);
      SecretKey cipherKey = factory.generateSecret(keySpec);
      
      String maskedPass = PBEUtils.encode64(pwd.getBytes(), algo, cipherKey, cipherSpec);
      
      return PicketBoxSecurityVault.PASS_MASK_PREFIX + maskedPass;
   }
   

   private Map<String, Object> getVaultOptionsMap(String keystore, String encDataDir, String alias, String salz, int iter,
         String password, Boolean createKeystore) throws Exception {
      Map<String, Object> options = new HashMap<String, Object>();
      options.put(PicketBoxSecurityVault.KEYSTORE_URL, keystore);
      options.put(PicketBoxSecurityVault.KEYSTORE_PASSWORD, getMaskedPassword(password, salz, iter));
      options.put(PicketBoxSecurityVault.KEYSTORE_ALIAS, alias);
      options.put(PicketBoxSecurityVault.SALT, salz);
      options.put(PicketBoxSecurityVault.ITERATION_COUNT, String.valueOf(iter));
      options.put(PicketBoxSecurityVault.ENC_FILE_DIR, encDataDir);
      if (createKeystore != null) {
         options.put(PicketBoxSecurityVault.CREATE_KEYSTORE, createKeystore.toString());
      }
      return options;
   }

   private Map<String, Object> getVaultOptionsMap(String keystore, String encDataDir, String alias, String salz, int iter,
                                                   String password) throws Exception {
      return getVaultOptionsMap(keystore, encDataDir, alias, salz, iter, password, null);
   }


   public static void setInitialVaulConditions(String originalKeyStoreFile, String targetKeyStoreFile,
         String originalVaultContentDir, String targetVaultContentDir) throws Exception {

      File tKS = new File(targetKeyStoreFile);
      File parent = tKS.getParentFile();
      if (!parent.exists()) {
         parent.mkdirs();
      }
      SecurityVaultUnitTestCase.copyFile(new File(originalKeyStoreFile), tKS);

      File targetVaultContent = new File(targetVaultContentDir);
      cleanDirectory(targetVaultContent);
      File originVault = new File(originalVaultContentDir);
      for (File f : originVault.listFiles()) {
         if (f.isFile()) // some version control systems add a hidden directory, we must make sure we won't copy those.
           SecurityVaultUnitTestCase.copyFile(f, new File(targetVaultContent.getAbsolutePath() + File.separator + f.getName()));
      }
   }

    /**
     * Make clean new directory.
     * 
     * @param directory
     */
    public static void cleanDirectory(File directory) {
       if (directory.exists()) {
           for (File f: directory.listFiles()) { f.delete(); }
           directory.delete();
       }
       directory.mkdirs();
    }
    
    /**
     * Copy file method.
     * 
     * @param sourceFile
     * @param destFile
     * @throws IOException
     */
     public static void copyFile(File sourceFile, File destFile) throws IOException {
         if (!destFile.exists()) {
             destFile.createNewFile();
         }
         FileInputStream fIn = null;
         FileOutputStream fOut = null;
         FileChannel source = null;
         FileChannel destination = null;
         try {
             fIn = new FileInputStream(sourceFile);
             source = fIn.getChannel();
             fOut = new FileOutputStream(destFile);
             destination = fOut.getChannel();
             long transfered = 0;
             long bytes = source.size();
             while (transfered < bytes) {
                 transfered += destination.transferFrom(source, 0, source.size());
                 destination.position(transfered);
             }
         } finally {
             if (source != null) {
                 source.close();
             } else if (fIn != null) {
                 fIn.close();
             }
             if (destination != null) {
                 destination.close();
             } else if (fOut != null) {
                 fOut.close();
             }
         }
     }

   static Class<?> loadClass(final Class<?> clazz, final String fqn) {
      return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
         public Class<?> run() {
            ClassLoader cl = clazz.getClassLoader();
            Class<?> loadedClass = null;
            try {
               loadedClass = cl.loadClass(fqn);
            } catch (ClassNotFoundException e) {
            }
            return loadedClass;
         }
      });

     }

   private void assertSecretValue(SecurityVault vault, String vaultBlock, String attributeName, String expectedSecuredAttributeValue) throws SecurityVaultException {
      assertEquals("Expected value has to match the one in vault. " + vaultBlock + ":" + attributeName + "=" + expectedSecuredAttributeValue,
            new String(expectedSecuredAttributeValue), 
            new String(vault.retrieve(vaultBlock, attributeName, null))); 
   }
   
   /**
    * get new instance of vault to simulate restart of application server
    * @return
    * @throws Exception
    */
   private SecurityVault getNewSecurityVaultInstance() throws Exception {
      Class<?> vaultClass = loadClass(SecurityVaultFactory.class, "org.picketbox.plugins.vault.PicketBoxSecurityVault");
      return (SecurityVault)vaultClass.newInstance();
   }
    
}