fixing failing ODBC test
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / database / CdmPersistentDataSource.java
index b37aca283dbbadb6c4c56b290e3b76d5d42d9b32..20a4522f43f9700bff573f2e0503eb057b9f95ef 100644 (file)
@@ -14,100 +14,82 @@ import static eu.etaxonomy.cdm.common.XmlHelp.insertXmlBean;
 import static eu.etaxonomy.cdm.common.XmlHelp.insertXmlValueProperty;\r
 import static eu.etaxonomy.cdm.common.XmlHelp.saveToXml;\r
 \r
-import java.io.File;\r
-import java.io.FileInputStream;\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
 import java.util.ArrayList;\r
 import java.util.Enumeration;\r
 import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Properties;\r
 \r
+import javax.sql.DataSource;\r
+\r
 import org.apache.log4j.Logger;\r
-import org.hibernate.cache.CacheProvider;\r
-import org.hibernate.cache.NoCacheProvider;\r
+import org.hibernate.cache.internal.NoCachingRegionFactory;\r
+import org.hibernate.cache.spi.RegionFactory;\r
 import org.jdom.Attribute;\r
-import org.jdom.Document;\r
 import org.jdom.Element;\r
-import org.jdom.output.Format;\r
 import org.springframework.beans.MutablePropertyValues;\r
 import org.springframework.beans.factory.config.BeanDefinition;\r
 import org.springframework.beans.factory.config.PropertiesFactoryBean;\r
 import org.springframework.beans.factory.support.AbstractBeanDefinition;\r
 import org.springframework.beans.factory.support.RootBeanDefinition;\r
-import org.springframework.jdbc.datasource.DriverManagerDataSource;\r
 \r
-import eu.etaxonomy.cdm.api.application.CdmApplicationUtils;\r
+import com.mchange.v2.c3p0.ComboPooledDataSource;\r
+\r
 import eu.etaxonomy.cdm.common.CdmUtils;\r
 import eu.etaxonomy.cdm.common.XmlHelp;\r
+import eu.etaxonomy.cdm.config.CdmPersistentSourceUtils;\r
+import eu.etaxonomy.cdm.config.CdmPersistentXMLSource;\r
+import eu.etaxonomy.cdm.config.CdmPersistentXMLSource.CdmSourceProperties;\r
+import eu.etaxonomy.cdm.config.ICdmPersistentSource;\r
 import eu.etaxonomy.cdm.database.types.IDatabaseType;\r
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;\r
 \r
 \r
 /**\r
  * class to access an CdmDataSource\r
  */\r
-public class CdmPersistentDataSource extends CdmDataSourceBase{\r
+public class CdmPersistentDataSource extends CdmDataSourceBase implements ICdmPersistentSource {\r
        private static final Logger logger = Logger.getLogger(CdmPersistentDataSource.class);\r
        \r
        public static final String DATASOURCE_BEAN_POSTFIX = "DataSource";\r
-       public final static String DATASOURCE_FILE_NAME = "cdm.datasources.xml";\r
-       public final static String DATASOURCE_PATH = "/eu/etaxonomy/cdm/";\r
+\r
+               \r
+       private String beanName;\r
+       private String dbUrl;\r
        \r
-       private final static Format format = Format.getPrettyFormat(); \r
-\r
-       public enum DbProperties{\r
-               DRIVER_CLASS,\r
-               URL,\r
-               USERNAME,\r
-               PASSWORD;\r
-\r
-               @Override\r
-               public String toString(){\r
-                       switch (this){\r
-                               case DRIVER_CLASS:\r
-                                       return "driverClassName";\r
-                               case URL:\r
-                                       return "url";\r
-                               case USERNAME:\r
-                                       return "username";\r
-                               case PASSWORD:\r
-                                       return "password";\r
-                               default: \r
-                                       throw new IllegalArgumentException( "Unknown enumeration type" );\r
-                       }\r
-               }\r
-       }\r
+       private String database;\r
        \r
-       //name\r
-       protected String dataSourceName;\r
+       /**\r
+        * This is strictly a <String, String> list of properties\r
+        */\r
+       private Properties cdmSourceProperties;\r
+\r
+       private List<Attribute> cdmSourceAttributes;\r
+\r
+\r
+       /**\r
+        * The Datasource class that Spring will use to set up the connection to the database\r
+        */\r
+       private static String dataSourceClassName = ComboPooledDataSource.class.getName();      \r
 \r
        \r
        /**\r
         * Returns the default CdmDataSource\r
         * @return the default CdmDataSource\r
+        * @throws DataSourceNotFoundException \r
         */\r
-       public final static CdmPersistentDataSource NewDefaultInstance(){\r
-               try {\r
-                       return NewInstance("default");\r
-               } catch (DataSourceNotFoundException e) {\r
-                       logger.error("Default datasource does not exist in config file");\r
-                       return null;\r
-               }\r
+       public final static CdmPersistentDataSource NewDefaultInstance() throws DataSourceNotFoundException {\r
+               return NewInstance("default");\r
        }\r
        \r
        \r
        /**\r
         * Returns the default CdmDataSource\r
         * @return the default CdmDataSource\r
+        * @throws DataSourceNotFoundException \r
         */\r
-       public final static CdmPersistentDataSource NewLocalHsqlInstance(){\r
-               try {\r
-                       return NewInstance("localDefaultHsql");\r
-               } catch (DataSourceNotFoundException e) {\r
-                       logger.error("Local datasource does not exist in config file");\r
-                       return null;\r
-               }\r
+       public final static CdmPersistentDataSource NewLocalHsqlInstance() throws DataSourceNotFoundException{\r
+               return NewInstance("localDefaultHsql");\r
        }\r
        \r
        /**\r
@@ -115,8 +97,7 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
         * @param strDataSource\r
         * @return\r
         */\r
-       public final static CdmPersistentDataSource NewInstance(String dataSourceName) \r
-                               throws DataSourceNotFoundException{\r
+       public final static CdmPersistentDataSource NewInstance(String dataSourceName) throws DataSourceNotFoundException{\r
                if (exists(dataSourceName)){\r
                        return new CdmPersistentDataSource(dataSourceName);\r
                }else{\r
@@ -129,195 +110,139 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
         * @param strDataSource\r
         */\r
        private CdmPersistentDataSource(String strDataSource){\r
-               dataSourceName = strDataSource;\r
-       }\r
-       \r
-       /**\r
-        * Returns the name of the bean.\r
-        * @return\r
-        */\r
-       public String getName(){\r
-               return dataSourceName;\r
+               setName(strDataSource);\r
+               loadSource(strDataSource);              \r
+       }\r
+       \r
+       private void loadSource(String strDataSource) {\r
+               CdmPersistentXMLSource cdmPersistentXMLSource = CdmPersistentXMLSource.NewInstance(strDataSource, DATASOURCE_BEAN_POSTFIX);\r
+               if(cdmPersistentXMLSource.getElement() != null) {\r
+                       beanName = cdmPersistentXMLSource.getBeanName();\r
+                       // properties from the persistent xml file \r
+                       cdmSourceProperties = cdmPersistentXMLSource.getCdmSourceProperties();\r
+                       cdmSourceAttributes = cdmPersistentXMLSource.getCdmSourceAttributes();\r
+                       \r
+                       // added database specific properties if they are null\r
+                       String url = getCdmSourceProperty(CdmSourceProperties.URL);\r
+                       DatabaseTypeEnum dbTypeEnum = getDatabaseType();\r
+                       if (dbTypeEnum != null && url != null){\r
+                               IDatabaseType dbType = dbTypeEnum.getDatabaseType();                            \r
+                               if (getCdmSourceProperty(CdmSourceProperties.DATABASE) == null){\r
+                                       String database = dbType.getDatabaseNameByConnectionString(url);\r
+                                       if(database != null) {\r
+                                               setDatabase(database);\r
+                                       }\r
+                               }\r
+                               if(getCdmSourceProperty(CdmSourceProperties.SERVER) == null){\r
+                                       String server = dbType.getServerNameByConnectionString(url);\r
+                                       if(server != null) {\r
+                                               setServer(server);\r
+                                       }\r
+                               }\r
+                               if(getCdmSourceProperty(CdmSourceProperties.PORT) == null){\r
+                                       int port = dbType.getPortByConnectionString(url); \r
+                                       if(port != 0) {\r
+                                               setPort(port);\r
+                                       }\r
+                               }\r
+                       }\r
+               }                                       \r
        }\r
        \r
-       \r
-       /**\r
-        * Returns the name of the bean Element in the xml config file.\r
-        * @return bean name\r
-        */\r
-       private static String getBeanName(String name){\r
-               return name == null? null : name + DATASOURCE_BEAN_POSTFIX;\r
+       public String getBeanName() {\r
+               return beanName;\r
        }\r
-\r
-\r
        \r
+       @Override\r
        public String getDatabase() {\r
-               return getDatabaseProperty("database");\r
+               return database;\r
        }\r
 \r
 \r
-       public String getFilePath() {\r
-               //TODO null\r
-               return getDatabaseProperty("filePath");\r
-       }\r
-\r
-\r
-       public H2Mode getMode() {\r
-               //TODO null\r
-               return H2Mode.fromString(getDatabaseProperty("mode"));\r
+       @Override\r
+       public void setDatabase(String database) {\r
+               this.database = database;\r
+               \r
        }\r
-\r
-       public int getPort() {\r
-               String port = CdmUtils.Nz(getDatabaseProperty("port"));\r
-               if ("".equals(port)){\r
-                       return -1;\r
-               }else{\r
-                       //TODO exception if non integer\r
-                       return Integer.valueOf(port);\r
-               }\r
+               \r
+       @Override\r
+       public String getFilePath() {           \r
+               return getCdmSourceProperty(CdmSourceProperties.FILEPATH);\r
        }\r
 \r
 \r
-       public String getServer() {\r
-               return getDatabaseProperty("server");\r
+       @Override\r
+       public H2Mode getMode() {               \r
+               return H2Mode.fromString(getCdmSourceProperty(CdmSourceProperties.MODE));\r
        }\r
-\r
-       /**\r
-        * Returns the database type of the data source. \r
-        * @return the database type of the data source. Null if the bean or the driver class property does not exist or the driver class is unknown.\r
-        */\r
-       public DatabaseTypeEnum getDatabaseType(){\r
-               Element bean = getDatasourceBeanXml(this.dataSourceName);\r
-               if (bean == null){\r
-                       return null;\r
-               }else{\r
-                       Element driverProp = XmlHelp.getFirstAttributedChild(bean, "property", "name", "driverClassName");\r
-                       if (driverProp == null){\r
-                               logger.warn("Unknown property driverClass");\r
-                       return null;\r
-                       }else{\r
-                               String strDriverClass = driverProp.getAttributeValue("value");\r
-                               DatabaseTypeEnum dbType = DatabaseTypeEnum.getDatabaseEnumByDriverClass(strDriverClass);\r
-                               return dbType;\r
-                       }\r
-               }\r
+       \r
+       @Override\r
+       public void setMode(H2Mode h2Mode) {\r
+               cdmSourceProperties.put(CdmSourceProperties.MODE.toString(), h2Mode.name());\r
+               \r
        }\r
        \r
+       @Override\r
+       public String getUsername(){\r
+               return getCdmSourceProperty(CdmSourceProperties.USERNAME);\r
+       }\r
        \r
-       /**\r
-        * Returns the database type of the data source. \r
-        * @return the database type of the data source. Null if the bean or the driver class property does not exist or the driver class is unknown.\r
-        */\r
-       protected String getDatabaseProperty(String property){\r
-               Element bean = getDatasourceBeanXml(this.dataSourceName);\r
-               String url;\r
-               String result = null;\r
-               if (bean != null){\r
-                       result = getPropertyValue(bean, property);\r
-                       if (result == null){  //test if property is database, server or port which are included in the url\r
-                               url = getPropertyValue(bean, "url");\r
-                               DatabaseTypeEnum dbTypeEnum = getDatabaseType();\r
-                               if (dbTypeEnum != null){\r
-                                       IDatabaseType dbType = dbTypeEnum.getDatabaseType();\r
-                                       if (property.equals("database")){\r
-                                               result = dbType.getDatabaseNameByConnectionString(url);\r
-                                       }else if(property.equals("server")){\r
-                                               result = dbType.getServerNameByConnectionString(url);\r
-                                       }else if(property.equals("port")){\r
-                                               result = String.valueOf(dbType.getPortByConnectionString(url));\r
-                                       }else{\r
-                                               logger.info("unknown property: " + property);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               return result;  \r
+       @Override\r
+       public void setUsername(String username) {\r
+               cdmSourceProperties.put(CdmSourceProperties.USERNAME.toString(), username);\r
+               \r
        }\r
        \r
-       private String getPropertyValue(Element bean, String property){\r
-               Element driverProp = XmlHelp.getFirstAttributedChild(bean, "property", "name", property);\r
-               if (driverProp == null){\r
-                       logger.info("Unknown property" + property);\r
-               return null;\r
-               }else{\r
-                       String strProperty = driverProp.getAttributeValue("value");\r
-                       return strProperty;\r
-               }\r
+       @Override\r
+       public String getPassword(){\r
+               return getCdmSourceProperty(CdmSourceProperties.PASSWORD);\r
        }\r
        \r
+       @Override\r
+       public void setPassword(String password) {\r
+               cdmSourceProperties.put(CdmSourceProperties.PASSWORD.toString(), password);\r
+               \r
+       }\r
 \r
+       @Override\r
+       public NomenclaturalCode getNomenclaturalCode() {\r
+               // TODO null\r
+               return NomenclaturalCode.fromString(getCdmSourceProperty(CdmSourceProperties.NOMENCLATURAL_CODE));\r
+       }\r
 \r
-       /**\r
-        * Returns the list of properties that are defined in the datasource    \r
-        * @return \r
-        */\r
-       @SuppressWarnings("unchecked")\r
-       public List<Attribute> getDatasourceAttributes(){\r
-               List<Attribute> result = new ArrayList<Attribute>();\r
-               Element bean = getDatasourceBeanXml(this.dataSourceName);\r
-               if (bean == null){\r
-                       return null;\r
-               }else{\r
-                       result = bean.getAttributes();\r
-               }\r
-               return result;\r
-       }       \r
-\r
-       /**\r
-        * Returns a defined property of the datasource\r
-        * @return the property of the data source. NULL if the datasource bean or the property does not exist.\r
-        */\r
-       public String getDatasourceProperty(DbProperties dbProp){\r
-               Element bean = getDatasourceBeanXml(this.dataSourceName);\r
-               if (bean == null){\r
-                       return null;\r
-               }else{\r
-                       Element elProperty = XmlHelp.getFirstAttributedChild(bean, "property", "name", dbProp.toString());\r
-                       if (elProperty == null){\r
-                               logger.warn("Unknown property: " + dbProp.toString());\r
-                       return null;\r
-                       }else{\r
-                               String strValue = elProperty.getAttributeValue("value");\r
-                               return strValue;\r
-                       }\r
-               }\r
+       @Override\r
+       public void setNomenclaturalCode(NomenclaturalCode nomenclaturalCode) {\r
+               cdmSourceProperties.put(CdmSourceProperties.NOMENCLATURAL_CODE.toString(), nomenclaturalCode.name());\r
        }\r
 \r
-       \r
-       /**\r
-        * Returns the list of properties that are defined in the datasource    \r
-        * @return \r
-        */\r
-       public Properties getDatasourceProperties(){\r
-               Properties result = new Properties();\r
-               Element bean = getDatasourceBeanXml(this.dataSourceName);\r
-               if (bean == null){\r
-                       return null;\r
-               }else{\r
-                       List<Element> elProperties = XmlHelp.getAttributedChildList(bean, "property", "name");\r
-                       Iterator<Element> iterator = elProperties.iterator();\r
-                       while(iterator.hasNext()){\r
-                               Element next = iterator.next();\r
-                               String strName = next.getAttributeValue("name");\r
-                               String strValue = next.getAttributeValue("value");\r
-                               result.put(strName, strValue);\r
-                       }\r
-               }\r
-               return result;\r
+\r
+\r
+       @Override\r
+       public DatabaseTypeEnum getDatabaseType(){\r
+               String strDriverClass = getCdmSourceProperty(CdmSourceProperties.DRIVER_CLASS);\r
+               DatabaseTypeEnum dbType = DatabaseTypeEnum.getDatabaseEnumByDriverClass(strDriverClass);\r
+               return dbType;\r
        }\r
+               \r
        \r
+       public String getCdmSourceProperty(CdmSourceProperties property){               \r
+               return cdmSourceProperties.getProperty(property.toString(),null);\r
+       }\r
+\r
        /**\r
-        * Returns a BeanDefinition object of type  DriverManagerDataSource that contains\r
+        * Returns a BeanDefinition object of type DataSource that contains\r
         * datsource properties (url, username, password, ...)\r
         * @return\r
         */\r
        @SuppressWarnings("unchecked")\r
+       @Override\r
        public BeanDefinition getDatasourceBean(){\r
-               DatabaseTypeEnum dbtype = DatabaseTypeEnum.getDatabaseEnumByDriverClass(getDatasourceProperty(DbProperties.DRIVER_CLASS));\r
+               DatabaseTypeEnum dbtype = \r
+                               DatabaseTypeEnum.getDatabaseEnumByDriverClass(getCdmSourceProperty(CdmSourceProperties.DRIVER_CLASS));\r
                \r
-               AbstractBeanDefinition bd = new RootBeanDefinition(dbtype.getDriverManagerDataSourceClass());\r
+               AbstractBeanDefinition bd = new RootBeanDefinition(dbtype.getDataSourceClass());\r
                //attributes\r
-               Iterator<Attribute> iterator = getDatasourceAttributes().iterator();\r
+               Iterator<Attribute> iterator = cdmSourceAttributes.iterator();\r
                while(iterator.hasNext()){\r
                        Attribute attribute = iterator.next();\r
                        if (attribute.getName().equals("lazy-init")){\r
@@ -335,11 +260,17 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                \r
                //properties\r
                MutablePropertyValues props = new MutablePropertyValues();\r
-               Properties persistentProperties = getDatasourceProperties();\r
-               Enumeration<String> keys = (Enumeration)persistentProperties.keys(); \r
+               \r
+               Enumeration<String> keys = (Enumeration)cdmSourceProperties.keys(); \r
                while (keys.hasMoreElements()){\r
                        String key = (String)keys.nextElement();\r
-                       props.addPropertyValue(key, persistentProperties.getProperty(key));\r
+                       \r
+                       if (key.equals("nomenclaturalCode") && cdmSourceProperties.getProperty(key).equals("ICBN")){\r
+                               //bugfix for old nomenclatural codes, remove if fixed elsewhere, see https://dev.e-taxonomy.eu/trac/ticket/3658\r
+                               props.addPropertyValue(key, NomenclaturalCode.ICNAFP.name());\r
+                       }else{\r
+                               props.addPropertyValue(key, cdmSourceProperties.getProperty(key));\r
+                       }\r
                }\r
 \r
                bd.setPropertyValues(props);\r
@@ -351,11 +282,13 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
         * @param showSql\r
         * @return\r
         */\r
+       @Override\r
        public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll){\r
                boolean showSql = false;\r
                boolean formatSql = false;\r
-               Class<? extends CacheProvider> cacheProviderClass = NoCacheProvider.class;\r
-               return getHibernatePropertiesBean(hbm2dll, showSql, formatSql, cacheProviderClass);\r
+               boolean registerSearchListener = false;\r
+               Class<? extends RegionFactory> cacheProviderClass = NoCachingRegionFactory.class;\r
+               return getHibernatePropertiesBean(hbm2dll, showSql, formatSql, registerSearchListener, cacheProviderClass);\r
        }\r
        \r
        \r
@@ -364,7 +297,8 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
         * @param showSql\r
         * @return\r
         */\r
-       public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll, Boolean showSql, Boolean formatSql, Class<? extends CacheProvider> cacheProviderClass){\r
+       @Override\r
+       public BeanDefinition getHibernatePropertiesBean(DbSchemaValidation hbm2dll, Boolean showSql, Boolean formatSql, Boolean registerSearchListener, Class<? extends RegionFactory> cacheProviderClass){\r
                //Hibernate default values\r
                if (hbm2dll == null){\r
                        hbm2dll = DbSchemaValidation.VALIDATE;\r
@@ -376,19 +310,23 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                        formatSql = false;\r
                }\r
                if (cacheProviderClass == null){\r
-                       cacheProviderClass = NoCacheProvider.class;\r
+                       cacheProviderClass = NoCachingRegionFactory.class;\r
                }\r
-               \r
+               if(registerSearchListener == null){\r
+                       registerSearchListener = false;\r
+               }\r
+                               \r
                DatabaseTypeEnum dbtype = getDatabaseType();\r
                AbstractBeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class);\r
                MutablePropertyValues hibernateProps = new MutablePropertyValues();\r
 \r
                Properties props = new Properties();\r
                props.setProperty("hibernate.hbm2ddl.auto", hbm2dll.toString());\r
-               props.setProperty("hibernate.dialect", dbtype.getHibernateDialect());\r
-               props.setProperty("hibernate.cache.provider_class", cacheProviderClass.getName());\r
+               props.setProperty("hibernate.dialect", dbtype.getHibernateDialectCanonicalName());\r
+               props.setProperty("hibernate.cache.region.factory_class", cacheProviderClass.getName());\r
                props.setProperty("hibernate.show_sql", String.valueOf(showSql));\r
                props.setProperty("hibernate.format_sql", String.valueOf(formatSql));\r
+               props.setProperty("hibernate.search.autoregister_listeners", String.valueOf(registerSearchListener));\r
 \r
                hibernateProps.addPropertyValue("properties",props);\r
                bd.setPropertyValues(hibernateProps);\r
@@ -401,83 +339,98 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
         * @return true if a datasource with the given name exists in the according datasource config file.\r
         */\r
        public static boolean exists(String strDataSourceName){\r
-               Element bean = getDatasourceBeanXml(strDataSourceName);\r
+               Element bean = CdmPersistentSourceUtils.getCdmSourceBeanXml(strDataSourceName, DATASOURCE_BEAN_POSTFIX);\r
                return (bean != null);\r
        }\r
 \r
+       /**\r
+        * @param strDataSourceName\r
+        * @param dataSource\r
+        * @param code \r
+        * @return\r
+        *                      the updated dataSource, null if not succesful\r
+        */\r
+       public static CdmPersistentDataSource update(String strDataSourceName,\r
+                       ICdmDataSource dataSource) throws DataSourceNotFoundException, IllegalArgumentException{\r
+               CdmPersistentSourceUtils.delete(CdmPersistentSourceUtils.getBeanName(strDataSourceName,DATASOURCE_BEAN_POSTFIX));\r
+               return save(strDataSourceName, dataSource);\r
+       }\r
        \r
        /**\r
-        * Saves or updates the datasource to the datasource config file.\r
-        * Uses default port.\r
-        * @param strDataSourceName name of the datasource (without postfix DataSource)\r
-        * @param databaseTypeEnum\r
-        * @param server\r
-        * @param database\r
-        * @param username\r
-        * @param password\r
-        * @return the CdmDataSource, null if not successful.\r
+        * Replace the persisted datasource with another one.\r
+        * Used primarily for renaming a datasource.\r
+        * \r
+        * @param strDataSourceName\r
+        * @param dataSource\r
+        * @return\r
+        * @throws DataSourceNotFoundException\r
+        * @throws IllegalArgumentException\r
         */\r
-       public static CdmPersistentDataSource save(String strDataSourceName, DatabaseTypeEnum databaseTypeEnum, String server, String database, \r
-                       String username, String password){\r
-               return save(strDataSourceName, databaseTypeEnum, server, database, \r
-                               databaseTypeEnum.getDefaultPort(), username, password);\r
+       public static CdmPersistentDataSource replace(String strDataSourceName,\r
+                       ICdmDataSource dataSource) throws DataSourceNotFoundException, IllegalArgumentException{\r
+               CdmPersistentSourceUtils.delete(CdmPersistentSourceUtils.getBeanName(strDataSourceName,DATASOURCE_BEAN_POSTFIX));\r
+               return save(dataSource);\r
        }\r
        \r
        /**\r
-        * Saves or updates the datasource to the datasource config file.\r
-        * @param strDataSourceName name of the datasource (without postfix DataSource)\r
+        * @param dataSource\r
+        * @return\r
+        * @throws IllegalArgumentException\r
+        */\r
+       public static CdmPersistentDataSource save(ICdmDataSource dataSource)  throws IllegalArgumentException {\r
+               return save(dataSource.getName(),dataSource);\r
+       }\r
+       \r
+       /**\r
+        * \r
+        * @param strDataSourceName\r
         * @param databaseTypeEnum\r
         * @param server\r
         * @param database\r
         * @param port\r
         * @param username\r
         * @param password\r
-        * @return the CdmDataSource, null if not successful.\r
+        * @param dataSourceClass\r
+        * @param initMethod\r
+        * @param destroyMethod\r
+        * @param startSilent\r
+        * @param startServer\r
+        * @param filePath\r
+        * @param mode\r
+        * @return\r
         */\r
-       public static CdmPersistentDataSource save(String strDataSourceName, DatabaseTypeEnum databaseTypeEnum, String server, String database, \r
-                               int port, String username, String password){\r
-               Class<? extends DriverManagerDataSource> driverManagerDataSource =  DriverManagerDataSource.class;\r
-               return save(strDataSourceName, databaseTypeEnum, server, database, port, username, password, driverManagerDataSource, null, null, null, null, null, null);\r
-       }\r
-       \r
-       \r
-       public static CdmPersistentDataSource saveLocalHsqlDb(String strDataSourceName, String databasePath, String databaseName, String username, String password){\r
-               DatabaseTypeEnum databaseTypeEnum = DatabaseTypeEnum.HSqlDb;\r
-               Class<? extends DriverManagerDataSource> driverManagerDataSource =  LocalHsqldb.class;\r
-               String server = "localhost";\r
-               int port = databaseTypeEnum.getDefaultPort();\r
-               return save(strDataSourceName, databaseTypeEnum, server, databaseName, port, username, password, driverManagerDataSource, "init", "destroy", true, true, databasePath, null);\r
-       }\r
-       \r
-       //\r
        private static CdmPersistentDataSource save(String strDataSourceName, \r
                        DatabaseTypeEnum databaseTypeEnum, \r
                        String server, \r
                        String database, \r
-                       int port, \r
+                       String port, \r
                        String username, \r
                        String password, \r
-                       Class<? extends DriverManagerDataSource> driverManagerDataSource,\r
+                       Class<? extends DataSource> dataSourceClass,\r
                        String initMethod,\r
                        String destroyMethod,\r
                        Boolean startSilent,\r
                        Boolean startServer, \r
                        String filePath,\r
-                       H2Mode mode\r
+                       H2Mode mode,\r
+                       NomenclaturalCode code\r
                ){\r
-               ICdmDataSource dataSource = new CdmDataSource(databaseTypeEnum, server, database, port, username, password, filePath, mode);\r
+               \r
+               int portNumber = "".equals(port) ? databaseTypeEnum.getDefaultPort() : Integer.valueOf(port);\r
+               \r
+               ICdmDataSource dataSource = new CdmDataSource(databaseTypeEnum, server, database, portNumber, username, password, filePath, mode, code);\r
                                \r
                //root\r
-               Element root = getBeansRoot(getDataSourceInputStream());\r
+               Element root = getBeansRoot(CdmPersistentSourceUtils.getCdmSourceInputStream());\r
                if (root == null){\r
                        return null;\r
                }\r
                //bean\r
-               Element bean = XmlHelp.getFirstAttributedChild(root, "bean", "id", getBeanName(strDataSourceName));\r
+               Element bean = XmlHelp.getFirstAttributedChild(root, "bean", "id", CdmPersistentSourceUtils.getBeanName(strDataSourceName, DATASOURCE_BEAN_POSTFIX));\r
                if (bean != null){\r
                        bean.detach();  //delete old version if necessary\r
                }\r
-               bean = insertXmlBean(root, getBeanName(strDataSourceName), driverManagerDataSource.getName());\r
+               bean = insertXmlBean(root, CdmPersistentSourceUtils.getBeanName(strDataSourceName, DATASOURCE_BEAN_POSTFIX), dataSourceClass.getName());\r
                //attributes\r
                bean.setAttribute("lazy-init", "true");\r
                if (initMethod != null) {bean.setAttribute("init-method", initMethod);}\r
@@ -493,9 +446,13 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                if (startServer != null) {insertXmlValueProperty(bean, "startServer", startServer.toString() );}\r
                if (filePath != null) {insertXmlValueProperty(bean, "filePath", filePath );}\r
                if (mode != null) {insertXmlValueProperty(bean, "mode", mode.toString() );}\r
+               if (code != null) {insertXmlValueProperty(bean, "nomenclaturalCode", code.name());}\r
                \r
                //save\r
-               saveToXml(root.getDocument(), getResourceDirectory(), DATASOURCE_FILE_NAME, format );\r
+               saveToXml(root.getDocument(), \r
+                               CdmPersistentSourceUtils.getResourceDirectory(), \r
+                               CdmPersistentXMLSource.CDMSOURCE_FILE_NAME, \r
+                               XmlHelp.prettyFormat );\r
                try {\r
                        return NewInstance(strDataSourceName) ;\r
                } catch (DataSourceNotFoundException e) {\r
@@ -504,17 +461,73 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                }\r
        }\r
        \r
-       \r
+\r
        /**\r
-        * Deletes a dataSource\r
+        * Saves a datasource to the datasource config file. If strDataSourceName differs a new dataSource\r
+        * will be created in config file. Use update() of real update functionality.\r
+        * \r
+        * @param strDataSourceName\r
         * @param dataSource\r
+        * @return\r
         */\r
-       public static void delete (CdmPersistentDataSource dataSource){\r
-               Element bean = getDatasourceBeanXml(dataSource.getName());\r
-               if (bean != null){\r
-                       Document doc = bean.getDocument();\r
-                       bean.detach();\r
-                       saveToXml(doc, getDataSourceOutputStream(), format );\r
+       public static CdmPersistentDataSource save(String strDataSourceName,\r
+                       ICdmDataSource dataSource)  throws IllegalArgumentException{\r
+               \r
+               if(dataSource.getDatabaseType() == null){\r
+                       new IllegalArgumentException("Database type not specified");\r
+               }\r
+               \r
+               if(dataSource.getDatabaseType().equals(DatabaseTypeEnum.H2)){\r
+                       Class<? extends DataSource> dataSourceClass =  LocalH2.class;\r
+                       if(dataSource.getMode() == null) {\r
+                               new IllegalArgumentException("H2 mode not specified");\r
+                       }                       \r
+                       return save(\r
+                                       strDataSourceName, \r
+                                       dataSource.getDatabaseType(), \r
+                                       "localhost", \r
+                                       getCheckedDataSourceParameter(dataSource.getDatabase()), \r
+                                       dataSource.getDatabaseType().getDefaultPort() + "", \r
+                                       getCheckedDataSourceParameter(dataSource.getUsername()), \r
+                                       getCheckedDataSourceParameter(dataSource.getPassword()), \r
+                                       dataSourceClass, \r
+                                       null, null, null, null, \r
+                                       dataSource.getFilePath(), \r
+                                       dataSource.getMode(),\r
+                                       dataSource.getNomenclaturalCode());\r
+               }else{\r
+                       \r
+                       Class<? extends DataSource> dataSourceClass;\r
+                       try {\r
+                               dataSourceClass = (Class<? extends DataSource>) Class.forName(dataSourceClassName);\r
+                               String server = getCheckedDataSourceParameter(dataSource.getServer());\r
+                               CdmPersistentDataSource persistendDatasource =  save(\r
+                                       strDataSourceName, \r
+                                       dataSource.getDatabaseType(), \r
+                                       getCheckedDataSourceParameter(dataSource.getServer()), \r
+                                       getCheckedDataSourceParameter(dataSource.getDatabase()), \r
+                                       dataSource.getPort() + "", \r
+                                       getCheckedDataSourceParameter(dataSource.getUsername()), \r
+                                       getCheckedDataSourceParameter(dataSource.getPassword()), \r
+                                       dataSourceClass, \r
+                                       null, null, null, null, null, null,\r
+                                       dataSource.getNomenclaturalCode());\r
+                               \r
+                               return persistendDatasource;\r
+                       } catch (ClassNotFoundException e) {\r
+                               logger.error("DataSourceClass not found - stopping application", e);\r
+                               System.exit(-1);\r
+                       }\r
+                       // will never be reached\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       private static String getCheckedDataSourceParameter(String parameter) throws IllegalArgumentException{          \r
+               if(parameter != null) {\r
+                       return parameter;\r
+               } else {\r
+                       throw new IllegalArgumentException("Non obsolete paramater was assigned a null value: " + parameter);\r
                }\r
        }\r
        \r
@@ -527,7 +540,7 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
        static public List<CdmPersistentDataSource> getAllDataSources(){\r
                List<CdmPersistentDataSource> dataSources = new ArrayList<CdmPersistentDataSource>();\r
                \r
-               Element root = getBeansRoot(getDataSourceInputStream());\r
+               Element root = getBeansRoot(CdmPersistentSourceUtils.getCdmSourceInputStream());\r
                if (root == null){\r
                        return null;\r
                }else{\r
@@ -544,94 +557,8 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                return dataSources;\r
        }\r
        \r
-       public String getUsername(){\r
-               return getDatasourceProperty(DbProperties.USERNAME);\r
-       }\r
-       \r
-       public String getPassword(){\r
-               return getDatasourceProperty(DbProperties.PASSWORD);\r
-       }\r
-\r
-\r
-       /* (non-Javadoc)\r
-        * @see java.lang.Object#toString()\r
-        */\r
-       public String toString(){\r
-               if (this.dataSourceName != null){\r
-                       return dataSourceName;\r
-               }else{\r
-                       return null;\r
-               }\r
-       }\r
-\r
-\r
-       \r
-       /**\r
-        * Returns the datasource config file input stream.\r
-        * @return data source config file input stream\r
-        */\r
-       static protected FileInputStream getDataSourceInputStream(){\r
-               String dir = getResourceDirectory();\r
-               File file = new File(dir + File.separator +  DATASOURCE_FILE_NAME);\r
-               return fileInputStream(file);\r
-       }\r
-       \r
-       \r
-       /**\r
-        * Returns the datasource config file outputStream.\r
-        * @return data source config file outputStream\r
-        */\r
-       static protected FileOutputStream getDataSourceOutputStream(){\r
-               String dir = getResourceDirectory();\r
-               File file = new File(dir + File.separator +  DATASOURCE_FILE_NAME);\r
-               return fileOutputStream(file);\r
-       }\r
-\r
-       /**\r
-        * Returns the jdom Element representing the data source bean in the config file.\r
-        * @return\r
-        */\r
-       private static Element getDatasourceBeanXml(String strDataSourceName){\r
-               FileInputStream inStream = getDataSourceInputStream();\r
-               Element root = getBeansRoot(inStream);\r
-               if (root == null){\r
-                       return null;\r
-               }else{\r
-               Element xmlBean = XmlHelp.getFirstAttributedChild(root, "bean", "id", getBeanName(strDataSourceName));\r
-                       if (xmlBean == null){\r
-                               //TODO warn or info\r
-                               logger.debug("Unknown Element 'bean id=" +strDataSourceName + "' ");\r
-                       };\r
-                       return xmlBean;\r
-               }\r
-       }\r
-       \r
-       // returns the directory containing the resources \r
-       private static String getResourceDirectory(){\r
-               File f = CdmApplicationUtils.getWritableResourceDir();\r
-               return f.getPath();\r
-       }\r
-       \r
-       static private FileInputStream fileInputStream(File file){\r
-               try {\r
-                       FileInputStream fis = new FileInputStream(file);\r
-                       return fis;\r
-               } catch (FileNotFoundException e) {\r
-                       logger.warn("File " + file == null?"null":file.getAbsolutePath() + " does not exist in the file system");\r
-                       return null;\r
-               }\r
-       }\r
-       \r
-       static private FileOutputStream fileOutputStream(File file){\r
-               try {\r
-                       FileOutputStream fos = new FileOutputStream(file);\r
-                       return fos;\r
-               } catch (FileNotFoundException e) {\r
-                       logger.warn("File " + (file == null?"null":file.getAbsolutePath()) + " does not exist in the file system");\r
-                       return null;\r
-               }\r
-       }\r
        \r
+       @Override\r
        public boolean equals(Object obj){\r
                if (obj == null){\r
                        return false;\r
@@ -639,8 +566,26 @@ public class CdmPersistentDataSource extends CdmDataSourceBase{
                        return false;\r
                }else{\r
                        CdmPersistentDataSource dataSource = (CdmPersistentDataSource)obj;\r
-                       return (this.dataSourceName == dataSource.dataSourceName);\r
+                       return (getName() == dataSource.getName());\r
                }\r
 \r
        }\r
+       \r
+       @Override\r
+       public String toString(){\r
+               if (getName() != null){\r
+                       return getName();\r
+               }else{\r
+                       return null;\r
+               }\r
+       }\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 }
\ No newline at end of file