catch up with branch daily

Signed-off-by: Ralf Mollik <ramollik@compex-commerce.com>
diff --git a/jenkins.build.config.xml b/jenkins.build.config.xml
index b5a47f4..9c87d0e 100644
--- a/jenkins.build.config.xml
+++ b/jenkins.build.config.xml
@@ -17,9 +17,15 @@
 <jenkins>
 	<!-- DO NOT EDIT BELOW THIS LINE -->
         <jenkins.build.dependencies>
+                <jenkins.build.dependency>org.eclipse.osbp.blob</jenkins.build.dependency>
                 <jenkins.build.dependency>org.eclipse.osbp.core.api</jenkins.build.dependency>
+                <jenkins.build.dependency>org.eclipse.osbp.dsl</jenkins.build.dependency>
+                <jenkins.build.dependency>org.eclipse.osbp.ecview.addons</jenkins.build.dependency>
+                <jenkins.build.dependency>org.eclipse.osbp.ecview.core</jenkins.build.dependency>
+                <jenkins.build.dependency>org.eclipse.osbp.jpa.services</jenkins.build.dependency>
                 <jenkins.build.dependency>org.eclipse.osbp.mondrian.api</jenkins.build.dependency>
                 <jenkins.build.dependency>org.eclipse.osbp.preferences</jenkins.build.dependency>
                 <jenkins.build.dependency>org.eclipse.osbp.runtime</jenkins.build.dependency>
+                <jenkins.build.dependency>org.eclipse.osbp.ui.api</jenkins.build.dependency>
         </jenkins.build.dependencies>
 </jenkins>
diff --git a/org.eclipse.osbp.persistence/META-INF/MANIFEST.MF b/org.eclipse.osbp.persistence/META-INF/MANIFEST.MF
index 0a41230..d966c37 100644
--- a/org.eclipse.osbp.persistence/META-INF/MANIFEST.MF
+++ b/org.eclipse.osbp.persistence/META-INF/MANIFEST.MF
@@ -18,7 +18,7 @@
  commons-vfs-osgi;bundle-version="[1.0.0,1.0.1)",
  jackrabbit-jcr-commons-osgi;bundle-version="[2.1.0,2.1.1)",
  jackrabbit-webdav-osgi;bundle-version="[2.3.3,2.3.4)",
- mondrian.osgi;bundle-version="[3.5.0,3.5.1)",
+ mondrian.osgi;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.persistence.jpa;bundle-version="2.6.0",
  org.eclipse.persistence.asm;bundle-version="3.3.1",
  org.eclipse.persistence.antlr;bundle-version="3.2.0",
@@ -27,14 +27,37 @@
  org.eclipse.osbp.gitinfo;bundle-version="[0.9.0,0.10.0)",
  org.eclipse.osbp.runtime.common;bundle-version="[0.9.0,0.10.0)",
  org.apache.felix.gogo.runtime,
- javax.validation.api
+ javax.validation.api,
+ org.h2;bundle-version="1.3.168",
+ joda-time;bundle-version="2.7.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.5.1",
+ org.eclipse.e4.ui.di;bundle-version="1.1.100",
+ org.eclipse.emf.ecore;bundle-version="2.12.0",
+ org.eclipse.emf.mwe.core;bundle-version="1.3.20",
+ org.eclipse.equinox.ds;bundle-version="1.4.400",
+ org.eclipse.osbp.blob;bundle-version="0.9.0",
+ org.eclipse.osbp.dsl.datatype.lib;bundle-version="0.9.0",
+ org.eclipse.osbp.dsl.dto.lib;bundle-version="0.9.0",
+ org.eclipse.osbp.ecview.core.common;bundle-version="0.9.0",
+ org.eclipse.osbp.ecview.dsl.lib;bundle-version="0.9.0",
+ org.eclipse.osbp.jpa.services;bundle-version="0.9.0",
+ org.eclipse.persistence.jpa.jpql;bundle-version="2.6.1",
+ org.joda.money;bundle-version="0.10.0",
+ org.eclipse.uomo.core;bundle-version="0.6.0",
+ org.eclipse.uomo.units;bundle-version="0.6.0",
+ org.eclipse.xtext.xbase.lib;bundle-version="2.11.0",
+ org.jsoup;bundle-version="1.8.3",
+ org.junit;bundle-version="4.12.0",
+ osgi.enterprise;bundle-version="4.2.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Vendor: Eclipse OSBP
 Import-Package: org.eclipse.osbp.core.api.persistence;version="0.9.0",
  org.eclipse.osbp.mondrian.api;version="0.9.0",
+ org.eclipse.osbp.ui.api.metadata;version="0.9.0",
  org.osgi.service.component;version="1.2.0",
  org.osgi.service.jdbc;version="1.0.0"
 Export-Package: org.eclipse.osbp.persistence
 Service-Component: OSGI-INF/*.xml
 Bundle-Activator: org.eclipse.osbp.persistence.Activator
 Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
diff --git a/org.eclipse.osbp.persistence/OSGI-INF/org.eclipse.osbp.persistence.PersistenceService.xml b/org.eclipse.osbp.persistence/OSGI-INF/org.eclipse.osbp.persistence.PersistenceService.xml
index a00f709..8dbfcd8 100644
--- a/org.eclipse.osbp.persistence/OSGI-INF/org.eclipse.osbp.persistence.PersistenceService.xml
+++ b/org.eclipse.osbp.persistence/OSGI-INF/org.eclipse.osbp.persistence.PersistenceService.xml
@@ -3,6 +3,7 @@
    <service>
       <provide interface="org.eclipse.osbp.core.api.persistence.IPersistenceService"/>
    </service>
+   <reference bind="bindDSLMetadataService" cardinality="1..1" interface="org.eclipse.osbp.ui.api.metadata.IDSLMetadataService" name="DSLMetadataService" policy="static" unbind="unbindDSLMetadataService"/>
    <reference bind="bindMondrianProvider" cardinality="1..1" interface="org.eclipse.osbp.mondrian.api.IMondrianManager" name="MondrianProvider" policy="dynamic" unbind="unbindMondrianProvider"/>
    <reference bind="bindValidationFactory" cardinality="1..1" interface="javax.validation.ValidatorFactory" name="ValidationFactory" policy="dynamic" unbind="unbindValidationFactory"/>
    <implementation class="org.eclipse.osbp.persistence.PersistenceService"/>
diff --git a/org.eclipse.osbp.persistence/build.properties b/org.eclipse.osbp.persistence/build.properties
index 5776bd7..02889b3 100644
--- a/org.eclipse.osbp.persistence/build.properties
+++ b/org.eclipse.osbp.persistence/build.properties
@@ -1,5 +1,9 @@
 output.. = target/classes/
-bin.includes = about.properties,  about.mappings,  about.ini,  about.html,  META-INF/,\
+bin.includes = about.properties,\
+               about.mappings,\
+               about.ini,\
+               about.html,\
+               META-INF/,\
                OSGI-INF/,\
                .settings/,\
                .,\
diff --git a/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/CustomPersistenceProvider.java b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/CustomPersistenceProvider.java
new file mode 100644
index 0000000..2df0129
--- /dev/null
+++ b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/CustomPersistenceProvider.java
@@ -0,0 +1,28 @@
+package org.eclipse.osbp.persistence;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManagerFactory;
+
+import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
+import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
+import org.eclipse.persistence.jpa.PersistenceProvider;
+import org.eclipse.persistence.tools.schemaframework.TableCreator;
+
+public class CustomPersistenceProvider extends PersistenceProvider {
+
+	public EntityManagerFactory createEntityManagerFactory(SEPersistenceUnitInfo puInfo, Properties properties) {
+		/** 
+		 * this static setting forces creating of tables and indexes although already existing
+		 * and creates late introduced indexes
+		 */
+        TableCreator.CHECK_EXISTENCE = true;
+        EntityManagerFactoryImpl emf = createEntityManagerFactoryImpl(puInfo, properties, true);
+        if(emf != null) {
+	        emf.close();
+	        TableCreator.CHECK_EXISTENCE = false;
+			return createEntityManagerFactoryImpl(puInfo, properties, true);
+        }
+        return null;
+	}
+}
diff --git a/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/EntityClassLoader.java b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/EntityClassLoader.java
new file mode 100644
index 0000000..715d793
--- /dev/null
+++ b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/EntityClassLoader.java
@@ -0,0 +1,49 @@
+package org.eclipse.osbp.persistence;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
+
+public class EntityClassLoader extends ClassLoader {
+	private IDSLMetadataService dslMetadataService;
+	private final Map<String, Class<?>> cachedClasses = new HashMap<>();
+	
+	public EntityClassLoader(ClassLoader parent, IDSLMetadataService dslMetadataService) {
+		super(parent);
+		this.dslMetadataService = dslMetadataService;
+	}
+
+	@Override
+	protected Class<?> findClass(String className) throws ClassNotFoundException {
+		if(cachedClasses.containsKey(className)) {
+			return cachedClasses.get(className);
+		}
+		return super.findClass(className);
+	}
+
+	@Override
+	public Class<?> loadClass(String className) throws ClassNotFoundException {
+		if(!cachedClasses.containsKey(className)) {
+			ClassLoader loader = dslMetadataService.getClassLoader(className);
+			if (loader != null) {
+				Class<?> clz = loader.loadClass(className);
+				cachedClasses.put(className, clz);
+				return clz;
+			} 
+			return super.loadClass(className);
+		} else {
+			return cachedClasses.get(className);
+		}
+	}
+
+	@Override
+	public InputStream getResourceAsStream(String resourceName) {
+		ClassLoader loader = dslMetadataService.getClassLoader(resourceName);
+		if (loader != null) {
+			return loader.getResourceAsStream(resourceName);
+		}
+		return super.getResourceAsStream(resourceName);
+	}
+}
diff --git a/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/PersistenceService.java b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/PersistenceService.java
index 40abe3f..48a91c6 100644
--- a/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/PersistenceService.java
+++ b/org.eclipse.osbp.persistence/src/org/eclipse/osbp/persistence/PersistenceService.java
@@ -20,6 +20,7 @@
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -28,7 +29,9 @@
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceException;
 import javax.sql.CommonDataSource;
+import javax.sql.ConnectionPoolDataSource;
 import javax.sql.DataSource;
 import javax.sql.XAConnection;
 import javax.sql.XADataSource;
@@ -39,12 +42,18 @@
 import org.eclipse.osbp.core.api.persistence.IPersistenceService;
 import org.eclipse.osbp.mondrian.api.IMondrianManager;
 import org.eclipse.osbp.mondrian.api.IMondrianService;
+import org.eclipse.osbp.preferences.DataSourceConfiguration.DataSourceItemDescription;
 import org.eclipse.osbp.preferences.ProductConfiguration;
+import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
 import org.eclipse.persistence.config.PersistenceUnitProperties;
 import org.eclipse.persistence.config.SystemProperties;
+import org.eclipse.persistence.config.TargetServer;
+import org.eclipse.persistence.exceptions.DatabaseException;
 import org.eclipse.persistence.internal.jpa.deployment.ArchiveFactoryImpl;
+import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
 import org.eclipse.persistence.jpa.PersistenceProvider;
 import org.eclipse.persistence.sessions.Session;
+import org.h2.tools.Server;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
@@ -67,66 +76,153 @@
 import mondrian.rolap.RolapConnection;
 import mondrian.server.Execution;
 
+/**
+ * The Class PersistenceService.
+ */
 @Component(service = IPersistenceService.class)
 public class PersistenceService implements IPersistenceService {
+	
+	/** The Constant OSGI_JNDI_SERVICE_NAME. */
 	public static final String OSGI_JNDI_SERVICE_NAME = "osgi.jndi.service.name";
+	
+	/** The Constant OSGI_JNDI_URL_PREFIX. */
 	public static final String OSGI_JNDI_URL_PREFIX = "osgi:service/";
+	
+	/** The Constant JAVAX_PERSISTENCE_PROVIDER_PROP. */
 	public static final String JAVAX_PERSISTENCE_PROVIDER_PROP = "javax.persistence.provider";
+	
+	/** The Constant PERSISTENCE_PROVIDER. */
 	public static final String PERSISTENCE_PROVIDER = "javax.persistence.spi.PersistenceProvider";
+	
+	/** The Constant ENTITYMANAGERFACTORY. */
 	public static final String ENTITYMANAGERFACTORY = "javax.persistence.EntityManagerFactory";
+	
+	/** The Constant OSGI_UNIT_NAME. */
 	public static final String OSGI_UNIT_NAME = "osgi.unit.name";
+	
+	/** The Constant FILTER_EMF. */
 	private static final String FILTER_EMF = "(objectClass=javax.persistence.EntityManagerFactory)";
+	
+	/** The Constant FILTER_EMF_WITH_PERSISTENCE. */
 	private static final String FILTER_EMF_WITH_PERSISTENCE = "(&(objectClass=javax.persistence.EntityManagerFactory)(osgi.unit.name=%s))";
 
+	/** The Constant log. */
 	private static final Logger log = LoggerFactory.getLogger(PersistenceService.class);
+	
+	/** The mondrian manager. */
 	private IMondrianManager mondrianManager;
 
+	/** The bundle context. */
 	private BundleContext bundleContext = null;
+	
+	/** The service registration. */
 	private ServiceRegistration<?> serviceRegistration;
+	
+	/** The ds props map. */
 	private Map<String, IDataSourceProperties> dsPropsMap = new HashMap<>();
+	
+	/** The ds map. */
 	private Map<String, CommonDataSource> dsMap = new HashMap<>();
+	
+	/** The persistence exception handler. */
 	private List<IPersistenceException> persistenceExceptionHandler = new ArrayList<>() ;
+	
+	/** The validator factory. */
 	private ValidatorFactory validatorFactory;
+	
+	/** The em factories. */
 	private HashMap<String, EntityManagerFactory> emFactories = new HashMap<>();
+	
+	/** The h2 servers. */
+	private Server tcpServer = null;
+	private Server webServer = null;
 
+	/** The entity class loader. */
+	private EntityClassLoader entityClassLoader;
+	
+	/** The dsl metadata service. */
+	protected static IDSLMetadataService dslMetadataService;
+
+
+	/**
+	 * Activate.
+	 *
+	 * @param context the context
+	 */
 	protected void activate(ComponentContext context) {
 		if (log.isDebugEnabled())
-			log.debug("PersistenceService activated");
+			log.debug("{}", "PersistenceService activated");
 		initialize(context);
 	}
 
+	/**
+	 * Deactivate.
+	 *
+	 * @param context the context
+	 */
 	protected void deactivate(ComponentContext context) { //NOSONAR
+		if(tcpServer != null) {
+			tcpServer.shutdown();
+		}
+		if(webServer != null) {
+			webServer.shutdown();
+		}
 		if (serviceRegistration != null) {
 			serviceRegistration.unregister();
 		} else {
 			if (log.isDebugEnabled())
-				log.debug("serviceRegistration not set, cannot unregister");
+				log.debug("{}", "serviceRegistration not set, cannot unregister");
 		}
 		if (log.isDebugEnabled())
-			log.debug("PersistenceService deactivated");
+			log.debug("{}", "PersistenceService deactivated");
 	}
 
+	/**
+	 * Bind mondrian provider.
+	 *
+	 * @param mondrianManager the mondrian manager
+	 */
 	@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
 	void bindMondrianProvider(IMondrianManager mondrianManager) {
 		this.mondrianManager = mondrianManager;
 	}
 
+	/**
+	 * Unbind mondrian provider.
+	 *
+	 * @param mondrianManager the mondrian manager
+	 */
 	void unbindMondrianProvider(IMondrianManager mondrianManager) {		//NOSONAR 
 		this.mondrianManager = null;
 	}
 
+	/**
+	 * Bind validation factory.
+	 *
+	 * @param validatorFactory the validator factory
+	 */
 	@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
 	void bindValidationFactory(ValidatorFactory validatorFactory) {
 		this.validatorFactory = validatorFactory;
 	}
 
+	/**
+	 * Unbind validation factory.
+	 *
+	 * @param validatorFactory the validator factory
+	 */
 	void unbindValidationFactory(ValidatorFactory validatorFactory) {	//NOSONAR
 		this.validatorFactory = null;
 	}
 
+	/**
+	 * Initialize.
+	 *
+	 * @param context the context
+	 */
 	public void initialize(ComponentContext context) {
 		if (log.isDebugEnabled())
-			log.debug("initializing PersistenceService");
+			log.debug("{}", "initializing PersistenceService");
 		bundleContext = context.getBundleContext();
 		// build properties map
 		createDataSourcePropertiesMap();
@@ -135,10 +231,19 @@
 		initDataSourceMap();
 		// register persistence provider in context
 		registerPersistenceProvider();
+		// our dynamic class loader
+		entityClassLoader = new EntityClassLoader(getClass().getClassLoader(), dslMetadataService);
+		// create all emf
+		createEntityManagerFactories();
 		if (log.isDebugEnabled())
-			log.debug("PersistenceService ready");
+			log.debug("{}", "PersistenceService ready");
 	}
 
+	/**
+	 * Show possible configuration errors.
+	 *
+	 * @param logger the logger
+	 */
 	public static void showPossibleConfigurationErrors(Logger logger) {
 		String[] messages = {
 				"Maybe misconfigured data sources? Verify configuration in Product properties for missing plugins or configuration!" };
@@ -147,6 +252,9 @@
 		}
 	}
 
+	/**
+	 * Creates the data source properties map.
+	 */
 	private void createDataSourcePropertiesMap() {
 		for (String name : ProductConfiguration.getDataSourceNames()) {
 			IDataSourceProperties dsProp = new DataSourceProperties(name);
@@ -156,13 +264,25 @@
 		}
 	}
 
+	/**
+	 * Lookup dsf.
+	 *
+	 * @param clientDriverName the client driver name
+	 * @return the data source factory
+	 */
 	private DataSourceFactory lookupDsf(String clientDriverName) {
 		String filter = "(&(" + DataSourceFactory.OSGI_JDBC_DRIVER_CLASS + "=" + clientDriverName + "))";
 		if (log.isDebugEnabled())
-			log.debug("Filter is: " + filter);
+			log.debug("Filter is: {}", filter);
 		return getDsf(filter);
 	}
 
+	/**
+	 * Gets the dsf.
+	 *
+	 * @param filter the filter
+	 * @return the dsf
+	 */
 	@SuppressWarnings("unchecked")
 	private DataSourceFactory getDsf(String filter) {
 		ServiceReference<DataSourceFactory>[] refs = null;
@@ -180,28 +300,93 @@
 		return (refs == null) ? null : bundleContext.getService(refs[0]);
 	}
 
-	private synchronized DataSource createDataSource(String jndiDatasource) {
-		DataSource ds = null;
+	/**
+	 * Creates the data source.
+	 *
+	 * @param jndiDatasource the jndi datasource
+	 * @return the connection pool data source
+	 */
+	private synchronized ConnectionPoolDataSource createDataSource(String jndiDatasource) {
+		ConnectionPoolDataSource ds = null;
 		try {
 			if (log.isDebugEnabled())
-				log.debug("createDataSource:" + jndiDatasource);
+				log.debug("createDataSource: {}", jndiDatasource);
 			IDataSourceProperties dsProps = dsPropsMap.get(jndiDatasource);
 			DataSourceFactory dsf = null;
 			if (dsProps != null) {
 				dsf = lookupDsf(dsProps.getClientDriverName());
 				if (dsf == null) {
-					log.error("Driver {} for {} not installed! If you want to use the driver, you have to add it to the .product configuration file!", dsProps.getClientDriverName(), jndiDatasource);
+					log.info("createDataSource: Driver {} for {} not installed! If you want to use the driver, you have to add it to the .product configuration file!", dsProps.getClientDriverName(), jndiDatasource);
 					return null;
 				}
 				Properties props=dsProps.getDataSourceProperties();
-				ds = dsf.createDataSource(props);
+				if ( log.isInfoEnabled() ) {
+					log.info("createDataSource: Driver {} for Datasource {} found with the following properties:", dsProps.getClientDriverName(), jndiDatasource);
+				    Iterator<Entry<Object, Object>> it = props.entrySet().iterator();
+				    while (it.hasNext()) {
+				        Entry<Object, Object> pair = it.next();
+				        if( pair.getKey().equals("password") ) {
+							if ( log.isDebugEnabled() ) {
+								log.debug("  {}={}", pair.getKey(), pair.getValue() );
+							} else {
+								log.info("  {}=******", pair.getKey() );
+							}
+				        } else {
+							log.info("  {}={}", pair.getKey(), pair.getValue() );
+				        }
+				    }
+				}
+				
+				ds = dsf.createConnectionPoolDataSource(props);
 				Hashtable<String, String> ht = new Hashtable<>();	// NOSONAR
 				ht.put(OSGI_JNDI_SERVICE_NAME, jndiDatasource);
-				bundleContext.registerService(DataSource.class, ds, ht);
+				if( bundleContext.registerService(ConnectionPoolDataSource.class, ds, ht) == null ) {
+					log.error("createDataSource: RegisterService for Driver {} for Datasource {} failed!", dsProps.getClientDriverName(), jndiDatasource);
+				}
 				if ( log.isInfoEnabled() ) {
-					log.info("Driver {} for Datasource {} found and registered!", dsProps.getClientDriverName(), jndiDatasource);
-					log.info("         url:        {}", props.getProperty("url"));
+					log.info("createDataSource: Driver {} for Datasource {} registered!", dsProps.getClientDriverName(), jndiDatasource);
+				}
+
+				if(ProductConfiguration.getDataSource(jndiDatasource).getValue(DataSourceItemDescription.SERVER_PORT) != null) {
+					Integer port = Integer.parseInt(ProductConfiguration.getDataSource(jndiDatasource).getValue(DataSourceItemDescription.SERVER_PORT));
+					if(tcpServer == null && dsProps.getClientDriverName().contains(".h2.") && port > 0) {
+						// create a h2 server for remote access
+						tcpServer = Server.createTcpServer("-tcp","-tcpAllowOthers","-tcpPort", port.toString()).start();
+						log.info("H2 TcpServer startet on port {}", port );
+					}
+					if(webServer == null && dsProps.getClientDriverName().contains(".h2.") && port > 0) {
+						// create a h2 server for remote access
+						port ++;
+						webServer = Server.createWebServer("-web","-webAllowOthers","-webPort", port.toString()).start();
+						log.info("H2 Web Server startet on port {}", port );
+					}
+				}
+			}
+		} catch (Exception e) {
+			log.error("createDataSource {} failed {}", jndiDatasource, e);
+		}
+		return ds;
+	}
+
+	private synchronized DataSource createSimpleDataSource(String jndiDatasource) {
+		DataSource ds = null;
+		try {
+			if (log.isDebugEnabled())
+				log.debug("createSimpleDataSource: {}", jndiDatasource);
+			IDataSourceProperties dsProps = dsPropsMap.get(jndiDatasource);
+			DataSourceFactory dsf = null;
+			if (dsProps != null) {
+				dsf = lookupDsf(dsProps.getClientDriverName());
+				if (dsf == null) {
+					log.info("createSimpleDataSource: Driver {} for {} not installed! If you want to use the driver, you have to add it to the .product configuration file!", dsProps.getClientDriverName(), jndiDatasource);
+					return null;
+				}
+				Properties props=dsProps.getDataSourceProperties();
+				if ( log.isInfoEnabled() ) {
+					log.info("createSimpleDataSource: Driver {} for Datasource {} found with the following properties:", dsProps.getClientDriverName(), jndiDatasource);
+					log.info("         url:        {}", props.getProperty("URL"));
 					log.info("         Servername: {}", props.getProperty("serverName"));
+					log.info("         Port:       {}", props.getProperty("portNumber"));
 					log.info("         Database:   {}", props.getProperty("databaseName"));
 					log.info("         User:       {}", props.getProperty("user"));
 				}
@@ -210,18 +395,48 @@
 				} else {
 					log.info("         Password:   {}", props.getProperty("password").replaceAll("..", "*#"));
 				}
+				
+				ds = dsf.createDataSource(props);
+				Hashtable<String, String> ht = new Hashtable<>();	// NOSONAR
+				ht.put(OSGI_JNDI_SERVICE_NAME, jndiDatasource);
+				if( bundleContext.registerService(DataSource.class, ds, ht) == null ) {
+					log.error("createSimpleDataSource: RegisterService for Driver {} for Datasource {} failed!", dsProps.getClientDriverName(), jndiDatasource);
+				}
+				if ( log.isInfoEnabled() ) {
+					log.info("createSimpleDataSource: Driver {} for Datasource {} registered!", dsProps.getClientDriverName(), jndiDatasource);
+				}
+
+				if(ProductConfiguration.getDataSource(jndiDatasource).getValue(DataSourceItemDescription.SERVER_PORT) != null) {
+					Integer port = Integer.parseInt(ProductConfiguration.getDataSource(jndiDatasource).getValue(DataSourceItemDescription.SERVER_PORT));
+					if(tcpServer == null && dsProps.getClientDriverName().contains(".h2.") && port > 0) {
+						// create a h2 server for remote access
+						tcpServer = Server.createTcpServer("-tcp","-tcpAllowOthers","-tcpPort", port.toString()).start();
+						log.info("H2 TcpServer startet on port {}", port );
+					}
+					if(webServer == null && dsProps.getClientDriverName().contains(".h2.") && port > 0) {
+						// create a h2 server for remote access
+						port ++;
+						webServer = Server.createWebServer("-web","-webAllowOthers","-webPort", port.toString()).start();
+						log.info("H2 Web Server startet on port {}", port );
+					}
+				}
 			}
 		} catch (Exception e) {
-			log.error("createDataSource '" + jndiDatasource + "' " + e.getClass().getCanonicalName(), e);
+			log.error("createSimpleDataSource {} failed {}", jndiDatasource, e);
 		}
 		return ds;
 	}
-
+	/**
+	 * Creates the XA data source.
+	 *
+	 * @param jndiDatasource the jndi datasource
+	 * @return the XA data source
+	 */
 	private synchronized XADataSource createXADataSource(String jndiDatasource) {
 		XADataSource ds = null;
 		try {
 			if (log.isDebugEnabled())
-				log.debug("createXADataSource:" + jndiDatasource);
+				log.debug("createXADataSource:{}", jndiDatasource);
 			IDataSourceProperties dsProps = dsPropsMap.get(jndiDatasource);
 			DataSourceFactory dsf = null;
 			if (dsProps != null) {
@@ -240,19 +455,36 @@
 		return ds;
 	}
 
+	/**
+	 * Lookup DS.
+	 *
+	 * @param jndiDatasource the jndi datasource
+	 * @return the data source
+	 * @throws NamingException the naming exception
+	 */
 	private DataSource lookupDS(String jndiDatasource) throws NamingException {
 		InitialContext ictx = new InitialContext();
 		return (DataSource) ictx.lookup(OSGI_JNDI_URL_PREFIX + jndiDatasource);
 	}
 
+	/**
+	 * Lookup XADS.
+	 *
+	 * @param jndiDatasource the jndi datasource
+	 * @return the XA data source
+	 * @throws NamingException the naming exception
+	 */
 	private XADataSource lookupXADS(String jndiDatasource) throws NamingException {
 		InitialContext ictx = new InitialContext();
 		return (XADataSource) ictx.lookup(OSGI_JNDI_URL_PREFIX + "XA" + jndiDatasource);
 	}
 
+	/**
+	 * Inits the data source map.
+	 */
 	public void initDataSourceMap() {
 		if (log.isDebugEnabled())
-			log.debug("initDataSourceMap");
+			log.debug("{}", "initDataSourceMap");
 		for (String jndiName : ProductConfiguration.getDataSourceNames()) {
 			CommonDataSource ds = getDataSource(jndiName);
 			if (ds != null) {
@@ -261,26 +493,43 @@
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getDataSource(java.lang.String)
+	 */
 	@Override
 	// must be checked if DataSource or XADatasource is returned
 	public CommonDataSource getDataSource(String jndiDatasource) {
 		if (log.isDebugEnabled())
-			log.debug("getDataSource:" + jndiDatasource);
+			log.debug("getDataSource:{}", jndiDatasource);
 		if (dsMap.containsKey(jndiDatasource)) {
 			return dsMap.get(jndiDatasource);
 		}
+		ConnectionPoolDataSource cpds = null;
+		try {
+			cpds = (ConnectionPoolDataSource) lookupDS(jndiDatasource);
+		} catch (NamingException e) {			// NOSONAR
+		} finally {
+			if (cpds == null) {
+				cpds = createDataSource(jndiDatasource);
+			}
+		}
+		if (cpds != null) {
+			return cpds;
+		}
+/*	
 		DataSource ds = null;
 		try {
 			ds = lookupDS(jndiDatasource);
 		} catch (NamingException e) {			// NOSONAR
 		} finally {
 			if (ds == null) {
-				ds = createDataSource(jndiDatasource);
+				ds = createSimpleDataSource(jndiDatasource);
 			}
 		}
 		if (ds != null) {
 			return ds;
 		}
+*/				
 		XADataSource xads = null;
 		try {
 			xads = lookupXADS(jndiDatasource);
@@ -293,40 +542,55 @@
 		return xads;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getJndiConnection(java.lang.String)
+	 */
 	@Override
 	public java.sql.Connection getJndiConnection(String jndiName) throws SQLException {
 		if (log.isDebugEnabled())
-			log.debug("getConnection:" + jndiName);
+			log.debug("getConnection:{}", jndiName);
 		if (dsMap.get(jndiName) instanceof DataSource) {
 			return ((DataSource) dsMap.get(jndiName)).getConnection();
 		}
 		return null;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getPersistenceUnitConnection(java.lang.String)
+	 */
 	@Override
 	public java.sql.Connection getPersistenceUnitConnection(String persistenceUnit) throws SQLException {
 		return getJndiConnection(ProductConfiguration.getPersistenceUnitJndiName(persistenceUnit));
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getXAJndiConnection(java.lang.String)
+	 */
 	@Override
 	public XAConnection getXAJndiConnection(String jndiName) throws SQLException {
 		if (log.isDebugEnabled())
-			log.debug("getXAConnection:" + jndiName);
+			log.debug("getXAConnection:{}", jndiName);
 		if (dsMap.get(jndiName) instanceof XADataSource) {
 			return ((XADataSource) dsMap.get(jndiName)).getXAConnection();
 		}
 		return null;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getXAPersistenceUnitConnection(java.lang.String)
+	 */
 	@Override
 	public XAConnection getXAPersistenceUnitConnection(String persistenceUnit) throws SQLException {
 		return getXAJndiConnection(ProductConfiguration.getPersistenceUnitJndiName(persistenceUnit));
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getMondrianConnection(java.lang.String, java.lang.String)
+	 */
 	@Override
 	public RolapConnection getMondrianConnection(String persistenceUnit, String cubePackageName) throws SQLException {
 		if (log.isDebugEnabled()) {
-			log.debug("mondrian connection:" + cubePackageName + " persistenceUnit:" + persistenceUnit);
+			log.debug("mondrian connection:{} persistenceUnit:{}", cubePackageName, persistenceUnit);
 		}
 
 		IMondrianService service = mondrianManager.getService(cubePackageName);
@@ -340,21 +604,30 @@
 		list.put("Catalog", service.getMondrianCatalogURL().toString());
 		String jndiName = ProductConfiguration.getPersistenceUnitJndiName(persistenceUnit);
 		if (log.isDebugEnabled())
-			log.debug("mondrian connection jndi:" + jndiName);
+			log.debug("mondrian connection jndi:{}", jndiName);
 		return (RolapConnection) DriverManager.getConnection(list, null, (DataSource) getDataSource(jndiName));
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#sendQuery(mondrian.rolap.RolapConnection, java.lang.String)
+	 */
 	@Override
 	public Result sendQuery(RolapConnection con, String query) {
 		return sendQuery(con, query, 10000);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#sendQuery(mondrian.rolap.RolapConnection, java.lang.String, long)
+	 */
 	@Override
 	public Result sendQuery(RolapConnection con, String query, long ms) {
 		log.debug("query: {}", query);
 		return con.execute(new Execution(con.parseQuery(query).getStatement(), ms));
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#clearMondrianCache()
+	 */
 	@Override
 	public void clearMondrianCache() {
 		for(IMondrianService service : mondrianManager.getAllServices()) {
@@ -379,6 +652,9 @@
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#clearCubeCache(mondrian.rolap.RolapConnection, java.lang.String)
+	 */
 	@Override
 	public void clearCubeCache(RolapConnection connection, String cubeName) {
 		Cube cube = connection.getSchema().lookupCube(cubeName, true);
@@ -390,6 +666,9 @@
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#clearJpaCache()
+	 */
 	@Override
 	public void clearJpaCache() {
 		for(EntityManagerFactory emf:emFactories.values()) {
@@ -397,23 +676,9 @@
 		}
 	}
 	
-	@Override
-	public void registerPersistenceUnit(String persistenceUnitName, Class<?> cls) {
-		registerPersistenceUnit(persistenceUnitName, cls.getClassLoader());		
-	}
-	
-	@Override
-	public void registerPersistenceUnit(String persistenceUnitName, ClassLoader classLoader) {
-		// lookup entity manager factory
-		if (emFactories.containsKey(persistenceUnitName)) {
-			return;
-		}
-		EntityManagerFactory emf = createEntityManagerFactory(persistenceUnitName, classLoader);
-		if (emf != null) {
-			emFactories.put(persistenceUnitName, emf);
-		}
-	}
-
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getEntityManagerFactory(java.lang.String)
+	 */
 	@Override
 	public EntityManagerFactory getEntityManagerFactory(String persistenceUnitName) {
 		if (emFactories.containsKey(persistenceUnitName)) {
@@ -423,9 +688,12 @@
 		return null;
 	}
 
+	/**
+	 * Register persistence provider.
+	 */
 	private void registerPersistenceProvider() {
 		// register persistence provider
-		PersistenceProvider persistence = new PersistenceProvider();
+		CustomPersistenceProvider persistence = new CustomPersistenceProvider();
 
 		Dictionary<String, String> props = new Hashtable<>();			// NOSONAR
 		props.put(JAVAX_PERSISTENCE_PROVIDER_PROP, persistence.getClass().getName());
@@ -433,29 +701,36 @@
 		// Required setting to be able to handle 'bundleresource' and 'bundleentry' protocol. DO NOT DELETE!
 		System.setProperty(SystemProperties.ARCHIVE_FACTORY, ArchiveFactoryImpl.class.getCanonicalName());
 		if (log.isDebugEnabled())
-			log.debug("persistence provider registered");
+			log.debug("{}", "persistence provider registered");
 	}
 
-	private EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, ClassLoader classLoader) {
+	/**
+	 * Creates the entity manager factory.
+	 *
+	 * @param persistenceUnitName the persistence unit name
+	 * @param classLoader the class loader
+	 * @return the entity manager factory
+	 */
+	private void createEntityManagerFactories() {
 		// retrieve persistence provider from context
 		EntityManagerFactory emf = null;
 		ServiceReference<?>[] refs = null;
-		String filter = "(&(" + JAVAX_PERSISTENCE_PROVIDER_PROP + "=org.eclipse.persistence.jpa.PersistenceProvider))";
+		String filter = "(&(" + JAVAX_PERSISTENCE_PROVIDER_PROP + "=" + CustomPersistenceProvider.class.getName() + "))";
 		try {
 			refs = bundleContext.getAllServiceReferences(PersistenceProvider.class.getName(), filter);
 		} catch (InvalidSyntaxException e) {
 			log.error("exception while retrieving persistence providers", e);
 		}
 		if ((refs == null) || (refs.length < 1)) {
-			log.error(
-					"no persistence providers found, therefore the entity manager factory was NOT created and NOT registered for unit name {}",
-							persistenceUnitName);
-		} else {
-			// register all persistence units' emfs
-			Properties properties = null;
+			log.error("{}", "no persistence providers found");
+			return;
+		}
+		CustomPersistenceProvider persistenceProvider = (CustomPersistenceProvider) bundleContext.getService(refs[0]);
+		// register all persistence units' emfs
+		for(String persistenceUnitName : ProductConfiguration.getPersistenceUnitNames()) {
 			String jndiName = ProductConfiguration.getPersistenceUnitJndiName(persistenceUnitName);
 			CommonDataSource ds = getDataSource(jndiName);
-			properties = ProductConfiguration.getPersistenceUnitProperties(persistenceUnitName, ds,	classLoader);
+			Properties properties = ProductConfiguration.getPersistenceUnitProperties(persistenceUnitName, ds,	entityClassLoader);
 			properties.put(PersistenceUnitProperties.DDL_GENERATION_INDEX_FOREIGN_KEYS, "true");
 			properties.put(PersistenceUnitProperties.VALIDATOR_FACTORY, validatorFactory);
 			properties.put(PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS, "org.eclipse.osbp.persistence.fragment.PersistenceExceptionHandler");
@@ -465,41 +740,49 @@
 			properties.put(PersistenceUnitProperties.WEAVING_FETCHGROUPS, "true");
 			properties.put(PersistenceUnitProperties.WEAVING_CHANGE_TRACKING, "true");
 			properties.put(PersistenceUnitProperties.LOGGING_PARAMETERS, "true");
+			properties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "commit");
+			properties.put(PersistenceUnitProperties.CONNECTION_POOL_INITIAL, "50");
+			properties.put(PersistenceUnitProperties.CONNECTION_POOL_MIN, "50");
+			properties.put(PersistenceUnitProperties.CONNECTION_POOL_MAX, "200");
+			properties.put(PersistenceUnitProperties.CONNECTION_POOL_READ+PersistenceUnitProperties.CONNECTION_POOL_SHARED, "true");
+			properties.put(PersistenceUnitProperties.TARGET_SERVER, TargetServer.None);
+
+			properties.put(PersistenceUnitProperties.JAVASE_DB_INTERACTION, "true");
+			properties.put(PersistenceUnitProperties.DDL_GENERATION_MODE, "both");
+			properties.put(PersistenceUnitProperties.APP_LOCATION, System.getProperty("user.home"));
+			properties.put(PersistenceUnitProperties.CREATE_JDBC_DDL_FILE, persistenceUnitName+".sql");
 			
-			PersistenceProvider persistenceProvider = (PersistenceProvider) bundleContext.getService(refs[0]);
 			if (log.isInfoEnabled())
-				log.info("create entity manager factory for persistenceUnit " + persistenceUnitName + " jndi "
-						+ jndiName + " with properties:" + properties.toString());
+				log.info("create entity manager factory for persistenceUnit '{}' jndi '{}' with properties {}", persistenceUnitName, jndiName, properties.toString());
 			try {
-				emf = persistenceProvider.createEntityManagerFactory(persistenceUnitName, properties);
-			} catch (/* DatabaseException | PersistenceException | */Exception dbe) {
-				log.error("creating entity manager factory for " + persistenceUnitName, dbe);
-			}
-			if (emf != null) {
-				Session session = emf.unwrap(Session.class);
-				persistenceExceptionHandler.add((IPersistenceException) session.getExceptionHandler());
-				// register this factory -- attention: the same xa and non xa
-				// will replace each other
-				Dictionary<String, String> emfprops = new Hashtable<>();	//NOSONAR
-				emfprops.put(ENTITYMANAGERFACTORY, emf.getClass().getName());
-				emfprops.put(OSGI_UNIT_NAME, persistenceUnitName);
-				bundleContext.registerService(EntityManagerFactory.class.getName(), emf, emfprops);
-				if (log.isInfoEnabled())
-					log.info("entity manager factory created and registered with unit name:" + persistenceUnitName);
-			} else {
-				log.error(
-						"incorrect persistence provider, therefore the entity manager factory was NOT created and NOT registered for unit name: {}",
-								persistenceUnitName);
+				SEPersistenceUnitInfo info = (SEPersistenceUnitInfo)dslMetadataService.getPersistenceUnitInfo(persistenceUnitName);
+				emf = persistenceProvider.createEntityManagerFactory(info, properties);
+				if (emf != null) {
+					Session session = emf.unwrap(Session.class);
+					persistenceExceptionHandler.add((IPersistenceException) session.getExceptionHandler());
+					// register this factory -- attention: the same xa and non xa
+					// will replace each other
+					Dictionary<String, String> emfprops = new Hashtable<>();	//NOSONAR
+					emfprops.put(ENTITYMANAGERFACTORY, emf.getClass().getName());
+					emfprops.put(OSGI_UNIT_NAME, persistenceUnitName);
+					bundleContext.registerService(EntityManagerFactory.class.getName(), emf, emfprops);
+					log.info("entity manager factory created and registered with unit name: {}", persistenceUnitName);
+					emFactories.put(persistenceUnitName, emf);
+				} else {
+					log.error("the entity manager factory was NOT created and NOT registered for unit name: {}", persistenceUnitName);
+				}
+			} catch (DatabaseException | PersistenceException dbe) {
+				log.error("creating entity manager factory for pu '{}' failed with {}.", persistenceUnitName, dbe);
 			}
 		}
-		return emf;
 	}
 
-	/**
-	 * Create the filter to find the proper service.
-	 * 
-	 * @return
-	 * @throws InvalidSyntaxException
+	/* Create the filter to find the proper service.
+	 *
+	 * @param context the context
+	 * @param persistenceUnitName the persistence unit name
+	 * @return the filter
+	 * @throws InvalidSyntaxException the invalid syntax exception
 	 */
 	@Override
 	public Filter createEMFFilter(ComponentContext context, String persistenceUnitName) throws InvalidSyntaxException {
@@ -511,11 +794,17 @@
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#getEntityManagerFactoryMap()
+	 */
 	@Override
 	public Map<String, EntityManagerFactory> getEntityManagerFactoryMap() {
 		return emFactories;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#inheritEntityManagerFactoryMap(java.util.Map)
+	 */
 	@Override
 	public void inheritEntityManagerFactoryMap(Map<String, EntityManagerFactory> entityManagerFactoryMap) {
 		for (Entry<String, EntityManagerFactory> persistenceUnit : entityManagerFactoryMap.entrySet()) {
@@ -523,8 +812,35 @@
 		}
 	}
 	
+	/* (non-Javadoc)
+	 * @see org.eclipse.osbp.core.api.persistence.IPersistenceService#registerPersistenceExceptionNotification(org.eclipse.osbp.core.api.persistence.IPersistenceException.Receiver)
+	 */
 	@Override
 	public void registerPersistenceExceptionNotification(IPersistenceException.Receiver receiver) {
 		persistenceExceptionHandler.forEach(it -> it.registerNotification(receiver));
 	}
+
+	/**
+	 * Bind persistence service.
+	 *
+	 * @param persistenceService
+	 *            the persistence service
+	 */
+	@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC)
+	public synchronized void bindDSLMetadataService(final IDSLMetadataService dslMetadataService) {
+		PersistenceService.dslMetadataService = dslMetadataService;
+		log.debug("DSLMetadataService bound");
+	}
+
+	/**
+	 * Unbind persistence service.
+	 *
+	 * @param persistenceService
+	 *            the persistence service
+	 */
+	public synchronized void unbindDSLMetadataService(final IDSLMetadataService dslMetadataService) { // NOSONAR
+		PersistenceService.dslMetadataService = null;
+		log.debug("DSLMetadataService unbound");
+	}
+
 }