You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/04/25 14:42:16 UTC
[1/2] AMBARI-5554 - Ambari Views : Persistence Data Store
Repository: ambari
Updated Branches:
refs/heads/trunk b137f0b9a -> fb57e05a5
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PersistenceConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PersistenceConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PersistenceConfigTest.java
new file mode 100644
index 0000000..3b20e37
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PersistenceConfigTest.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * PersistenceConfig tests.
+ */
+public class PersistenceConfigTest {
+ private final static String xml = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " </instance>\n" +
+ " <persistence>\n" +
+ " <entity>\n" +
+ " <class>org.apache.ambari.server.view.TestEntity1</class>\n" +
+ " <id-property>id</id-property>\n" +
+ " </entity>\n" +
+ " <entity>\n" +
+ " <class>org.apache.ambari.server.view.TestEntity2</class>\n" +
+ " <id-property>name</id-property>\n" +
+ " </entity>\n" +
+ " </persistence>" +
+ "</view>";
+
+ private final static String xml_no_entities = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " </instance>\n" +
+ " <persistence>\n" +
+ " </persistence>" +
+ "</view>";
+
+ private final static String xml_no_persistence = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " </instance>\n" +
+ " <persistence>\n" +
+ " </persistence>" +
+ "</view>";
+
+ @Test
+ public void testGetEntities() throws Exception {
+ ViewConfig config = ViewConfigTest.getConfig(xml);
+ PersistenceConfig persistenceConfig = config.getPersistence();
+ Assert.assertEquals(2, persistenceConfig.getEntities().size());
+
+ config = ViewConfigTest.getConfig(xml_no_entities);
+ persistenceConfig = config.getPersistence();
+ Assert.assertTrue(persistenceConfig.getEntities().isEmpty());
+
+ config = ViewConfigTest.getConfig(xml_no_persistence);
+ persistenceConfig = config.getPersistence();
+ Assert.assertTrue(persistenceConfig.getEntities().isEmpty());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java
new file mode 100644
index 0000000..2ec0442
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java
@@ -0,0 +1,447 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.persistence;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityTest;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.view.configuration.EntityConfig;
+import org.apache.ambari.server.view.configuration.InstanceConfig;
+import org.apache.ambari.server.view.configuration.InstanceConfigTest;
+import org.apache.ambari.server.view.configuration.ViewConfig;
+import org.apache.ambari.server.view.configuration.ViewConfigTest;
+import org.easymock.Capture;
+import org.eclipse.persistence.dynamic.DynamicClassLoader;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.tools.schemaframework.SchemaManager;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Query;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * DataStoreImpl tests.
+ */
+public class DataStoreImplTest {
+ private final static String xml = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " </instance>\n" +
+ " <persistence>\n" +
+ " <entity>\n" +
+ " <class>org.apache.ambari.server.view.persistence.DataStoreImplTest$TestEntity</class>\n" +
+ " <id-property>id</id-property>\n" +
+ " </entity>\n" +
+ " </persistence>" +
+ "</view>";
+
+ @Test
+ public void testStore_create() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ EntityTransaction transaction = createMock(EntityTransaction.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ expect(entityManager.getTransaction()).andReturn(transaction).anyTimes();
+
+ Capture<Class> entityClassCapture = new Capture<Class>();
+ expect(entityManager.find(capture(entityClassCapture), eq(99))).andReturn(null);
+ Capture<DynamicEntity> entityCapture = new Capture<DynamicEntity>();
+ entityManager.persist(capture(entityCapture));
+ entityManager.close();
+
+ transaction.begin();
+ transaction.commit();
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ dataStore.store(new TestEntity(99, "foo"));
+
+ Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass());
+ Assert.assertEquals(99, entityCapture.getValue().get("id"));
+ Assert.assertEquals("foo", entityCapture.getValue().get("name"));
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager);
+ }
+
+ @Test
+ public void testStore_update() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ EntityTransaction transaction = createMock(EntityTransaction.class);
+ DynamicEntity dynamicEntity = createMock(DynamicEntity.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ expect(entityManager.getTransaction()).andReturn(transaction).anyTimes();
+
+ Capture<Class> entityClassCapture = new Capture<Class>();
+ expect(entityManager.find(capture(entityClassCapture), eq(99))).andReturn(dynamicEntity);
+ entityManager.close();
+
+ expect(dynamicEntity.set("id", 99)).andReturn(dynamicEntity);
+ expect(dynamicEntity.set("name", "foo")).andReturn(dynamicEntity);
+
+ transaction.begin();
+ transaction.commit();
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ dataStore.store(new TestEntity(99, "foo"));
+
+ Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass());
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity);
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ EntityTransaction transaction = createMock(EntityTransaction.class);
+ DynamicEntity dynamicEntity = createMock(DynamicEntity.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ expect(entityManager.getTransaction()).andReturn(transaction).anyTimes();
+ Capture<Class> entityClassCapture = new Capture<Class>();
+ expect(entityManager.getReference(capture(entityClassCapture), eq(99))).andReturn(dynamicEntity);
+ entityManager.remove(dynamicEntity);
+ entityManager.close();
+
+ transaction.begin();
+ transaction.commit();
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ dataStore.remove(new TestEntity(99, "foo"));
+
+ Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass());
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity);
+ }
+
+ @Test
+ public void testFind() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ DynamicEntity dynamicEntity = createMock(DynamicEntity.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ Capture<Class> entityClassCapture = new Capture<Class>();
+ expect(entityManager.find(capture(entityClassCapture), eq(99))).andReturn(dynamicEntity);
+ entityManager.close();
+
+ expect(dynamicEntity.get("id")).andReturn(99);
+ expect(dynamicEntity.get("name")).andReturn("foo");
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper, dynamicEntity, schemaManager);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ TestEntity entity = dataStore.find(TestEntity.class, 99);
+
+ Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass());
+ Assert.assertEquals(99, entity.getId());
+ Assert.assertEquals("foo", entity.getName());
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper, dynamicEntity, schemaManager);
+ }
+
+ @Test
+ public void testFindAll() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ DynamicEntity dynamicEntity = createMock(DynamicEntity.class);
+ Query query = createMock(Query.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ expect(entityManager.createQuery(
+ "SELECT e FROM DataStoreImplTest$TestEntity1 e WHERE e.id=99")).andReturn(query);
+ entityManager.close();
+
+ expect(query.getResultList()).andReturn(Collections.singletonList(dynamicEntity));
+
+ expect(dynamicEntity.get("id")).andReturn(99);
+ expect(dynamicEntity.get("name")).andReturn("foo");
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper, dynamicEntity, query, schemaManager);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ Collection<TestEntity> entities = dataStore.findAll(TestEntity.class, "id=99");
+
+ Assert.assertEquals(1, entities.size());
+
+ TestEntity entity = entities.iterator().next();
+
+ Assert.assertEquals(99, entity.getId());
+ Assert.assertEquals("foo", entity.getName());
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper, dynamicEntity, query, schemaManager);
+ }
+
+ @Test
+ public void testFindAll_multiple() throws Exception {
+ DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());
+
+ // create mocks
+ EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class);
+ EntityManager entityManager = createMock(EntityManager.class);
+ JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class);
+ SchemaManager schemaManager = createNiceMock(SchemaManager.class);
+ DynamicEntity dynamicEntity1 = createMock(DynamicEntity.class);
+ DynamicEntity dynamicEntity2 = createMock(DynamicEntity.class);
+ DynamicEntity dynamicEntity3 = createMock(DynamicEntity.class);
+ Query query = createMock(Query.class);
+
+ // set expectations
+ Capture<DynamicType> typeCapture = new Capture<DynamicType>();
+ jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture));
+
+ expect(entityManagerFactory.createEntityManager()).andReturn(entityManager);
+ expect(entityManager.createQuery(
+ "SELECT e FROM DataStoreImplTest$TestEntity1 e WHERE e.name='foo'")).andReturn(query);
+ entityManager.close();
+
+ List<DynamicEntity> entityList = new LinkedList<DynamicEntity>();
+ entityList.add(dynamicEntity1);
+ entityList.add(dynamicEntity2);
+ entityList.add(dynamicEntity3);
+
+ expect(query.getResultList()).andReturn(entityList);
+
+ expect(dynamicEntity1.get("id")).andReturn(99);
+ expect(dynamicEntity1.get("name")).andReturn("foo");
+
+ expect(dynamicEntity2.get("id")).andReturn(100);
+ expect(dynamicEntity2.get("name")).andReturn("foo");
+
+ expect(dynamicEntity3.get("id")).andReturn(101);
+ expect(dynamicEntity3.get("name")).andReturn("foo");
+
+ // replay mocks
+ replay(entityManagerFactory, entityManager, jpaDynamicHelper,
+ dynamicEntity1, dynamicEntity2, dynamicEntity3, query, schemaManager);
+
+ DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager);
+
+ Collection<TestEntity> entities = dataStore.findAll(TestEntity.class, "name='foo'");
+
+ Assert.assertEquals(3, entities.size());
+
+ for (TestEntity entity : entities) {
+ Assert.assertEquals("foo", entity.getName());
+ }
+
+ // verify mocks
+ verify(entityManagerFactory, entityManager, jpaDynamicHelper,
+ dynamicEntity1, dynamicEntity2, dynamicEntity3, query, schemaManager);
+ }
+
+ private DataStoreImpl getDataStore(EntityManagerFactory entityManagerFactory,
+ JPADynamicHelper jpaDynamicHelper,
+ DynamicClassLoader classLoader,
+ SchemaManager schemaManager)
+ throws Exception {
+ ViewConfig viewConfig = ViewConfigTest.getConfig(xml);
+ ViewEntity viewDefinition = ViewEntityTest.getViewEntity(viewConfig);
+
+ InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
+ ViewInstanceEntity viewInstanceEntity = new ViewInstanceEntity(viewDefinition, instanceConfig);
+
+ setPersistenceEntities(viewInstanceEntity);
+
+ Injector injector = Guice.createInjector(
+ new TestModule(viewInstanceEntity, entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager));
+ return injector.getInstance(DataStoreImpl.class);
+ }
+
+
+ // TODO : move to ViewEntityEntity test.
+ private static void setPersistenceEntities(ViewInstanceEntity viewInstanceDefinition) {
+ ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
+ Collection<ViewEntityEntity> entities = new HashSet<ViewEntityEntity>();
+
+ ViewConfig viewConfig = viewDefinition.getConfiguration();
+ for (EntityConfig entityConfiguration : viewConfig.getPersistence().getEntities()) {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+
+ viewEntityEntity.setId(1L);
+ viewEntityEntity.setViewName(viewDefinition.getName());
+ viewEntityEntity.setViewInstanceName(viewInstanceDefinition.getName());
+ viewEntityEntity.setClassName(entityConfiguration.getClassName());
+ viewEntityEntity.setIdProperty(entityConfiguration.getIdProperty());
+ viewEntityEntity.setViewInstance(viewInstanceDefinition);
+
+ entities.add(viewEntityEntity);
+ }
+ viewInstanceDefinition.setEntities(entities);
+ }
+
+
+ public static class TestEntity {
+
+ public TestEntity() {
+ }
+
+ public TestEntity(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ int id;
+ String name;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+ private static class TestModule implements Module, SchemaManagerFactory {
+ private final ViewInstanceEntity viewInstanceEntity;
+ private final EntityManagerFactory entityManagerFactory;
+ private final JPADynamicHelper jpaDynamicHelper;
+ private final DynamicClassLoader classLoader;
+ private final SchemaManager schemaManager;
+
+ private TestModule(ViewInstanceEntity viewInstanceEntity, EntityManagerFactory entityManagerFactory,
+ JPADynamicHelper jpaDynamicHelper, DynamicClassLoader classLoader,
+ SchemaManager schemaManager) {
+ this.viewInstanceEntity = viewInstanceEntity;
+ this.entityManagerFactory = entityManagerFactory;
+ this.jpaDynamicHelper = jpaDynamicHelper;
+ this.classLoader = classLoader;
+ this.schemaManager = schemaManager;
+ }
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(ViewInstanceEntity.class).toInstance(viewInstanceEntity);
+ binder.bind(EntityManagerFactory.class).toInstance(entityManagerFactory);
+ binder.bind(JPADynamicHelper.class).toInstance(jpaDynamicHelper);
+ binder.bind(DynamicClassLoader.class).toInstance(classLoader);
+ binder.bind(SchemaManagerFactory.class).toInstance(this);
+ }
+
+ @Override
+ public SchemaManager getSchemaManager(DatabaseSession session) {
+ return schemaManager;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-views/src/main/java/org/apache/ambari/view/DataStore.java
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/java/org/apache/ambari/view/DataStore.java b/ambari-views/src/main/java/org/apache/ambari/view/DataStore.java
new file mode 100644
index 0000000..1cbbecb
--- /dev/null
+++ b/ambari-views/src/main/java/org/apache/ambari/view/DataStore.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view;
+
+import java.util.Collection;
+
+/**
+ * View data store.
+ */
+public interface DataStore {
+
+ /**
+ * Save the given entity to persistent storage. The entity must be declared as an
+ * <entity> in the <persistence> element of the view.xml.
+ *
+ * @param entity the entity to be persisted.
+ *
+ * @throws PersistenceException thrown if the given entity can not be persisted
+ */
+ public void store(Object entity) throws PersistenceException;
+
+ /**
+ * Remove the given entity from persistent storage.
+ *
+ * @param entity the entity to be removed.
+ *
+ * @throws PersistenceException thrown if the given entity can not be removed
+ */
+ public void remove(Object entity) throws PersistenceException;
+
+ /**
+ * Find the entity of the given class type that is uniquely identified by the
+ * given primary key.
+ *
+ * @param clazz the entity class
+ * @param primaryKey the primary key
+ * @param <T> the entity type
+ *
+ * @return the entity; null if the entity can't be found
+ *
+ * @throws PersistenceException thrown if an error occurs trying to find the entity
+ */
+ public <T> T find(Class<T> clazz, Object primaryKey) throws PersistenceException;
+
+ /**
+ * Find all the entities for the given where clause. Specifying null for the where
+ * clause should return all entities of the given class type.
+ *
+ * @param clazz the entity class
+ * @param whereClause the where clause; may be null
+ * @param <T> the entity type
+ *
+ * @return all of the entities for the given where clause; empty collection if no
+ * entities can be found
+ *
+ * @throws PersistenceException
+ */
+ public <T> Collection<T> findAll(Class<T> clazz, String whereClause) throws PersistenceException;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java b/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java
new file mode 100644
index 0000000..6e32940
--- /dev/null
+++ b/ambari-views/src/main/java/org/apache/ambari/view/PersistenceException.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view;
+
+/**
+ * View persistence exception. Indicates that an error occurred while
+ * persisting a view or view data.
+ */
+public class PersistenceException extends Exception {
+ /**
+ * Constructor.
+ *
+ * @param msg message
+ */
+ public PersistenceException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param msg message
+ * @param throwable root exception
+ */
+ public PersistenceException(String msg, Throwable throwable) {
+ super(msg, throwable);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java
index 8a00d4d..898e8f5 100644
--- a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java
+++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java
@@ -115,4 +115,11 @@ public interface ViewContext {
* @return a stream provider
*/
public URLStreamProvider getURLStreamProvider();
+
+ /**
+ * Get a data store for view persistence entities.
+ *
+ * @return a data store
+ */
+ public DataStore getDataStore();
}
[2/2] git commit: AMBARI-5554 - Ambari Views : Persistence Data Store
Posted by tb...@apache.org.
AMBARI-5554 - Ambari Views : Persistence Data Store
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fb57e05a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fb57e05a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fb57e05a
Branch: refs/heads/trunk
Commit: fb57e05a5a40b012d76cacbd55b257e338b884b9
Parents: b137f0b
Author: tbeerbower <tb...@hortonworks.com>
Authored: Wed Apr 23 22:49:48 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Fri Apr 25 08:11:05 2014 -0400
----------------------------------------------------------------------
.../server/controller/ControllerModule.java | 122 ++--
.../apache/ambari/server/orm/dao/ViewDAO.java | 2 +-
.../ambari/server/orm/entities/ViewEntity.java | 11 +-
.../server/orm/entities/ViewEntityEntity.java | 187 ++++++
.../server/orm/entities/ViewInstanceEntity.java | 24 +
.../server/upgrade/UpgradeCatalog160.java | 24 +
.../ambari/server/view/ViewContextImpl.java | 19 +
.../apache/ambari/server/view/ViewRegistry.java | 37 +-
.../server/view/configuration/EntityConfig.java | 43 ++
.../view/configuration/PersistenceConfig.java | 45 ++
.../server/view/configuration/ViewConfig.java | 15 +
.../server/view/persistence/DataStoreImpl.java | 603 +++++++++++++++++++
.../view/persistence/DataStoreModule.java | 118 ++++
.../view/persistence/SchemaManagerFactory.java | 36 ++
.../main/resources/Ambari-DDL-MySQL-CREATE.sql | 3 +
.../main/resources/Ambari-DDL-Oracle-CREATE.sql | 3 +
.../resources/Ambari-DDL-Postgres-CREATE.sql | 6 +-
.../src/main/resources/META-INF/persistence.xml | 11 +
.../orm/entities/ViewEntityEntityTest.java | 113 ++++
.../server/orm/entities/ViewEntityTest.java | 10 +
.../server/upgrade/UpgradeCatalog160Test.java | 71 +++
.../view/configuration/EntityConfigTest.java | 79 +++
.../configuration/PersistenceConfigTest.java | 83 +++
.../view/persistence/DataStoreImplTest.java | 447 ++++++++++++++
.../java/org/apache/ambari/view/DataStore.java | 75 +++
.../ambari/view/PersistenceException.java | 44 ++
.../org/apache/ambari/view/ViewContext.java | 7 +
27 files changed, 2178 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 86c11cb..c132b1d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -102,6 +102,9 @@ public class ControllerModule extends AbstractModule {
private boolean dbInitNeeded;
private final Gson prettyGson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
+
+ // ----- Constructors ------------------------------------------------------
+
public ControllerModule() throws Exception {
configuration = new Configuration();
hostsMap = new HostsMap(configuration);
@@ -112,6 +115,48 @@ public class ControllerModule extends AbstractModule {
hostsMap = new HostsMap(configuration);
}
+
+ // ----- ControllerModule --------------------------------------------------
+
+ /**
+ * Get the common persistence related configuration properties.
+ *
+ * @return the configuration properties
+ */
+ public static Properties getPersistenceProperties(Configuration configuration) {
+ Properties properties = new Properties();
+
+ // custom jdbc properties
+ Map<String, String> custom = configuration.getDatabaseCustomProperties();
+
+ if (0 != custom.size()) {
+ for (Entry<String, String> entry : custom.entrySet()) {
+ properties.setProperty("eclipselink.jdbc.property." + entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ switch (configuration.getPersistenceType()) {
+ case IN_MEMORY:
+ properties.setProperty(JDBC_URL, Configuration.JDBC_IN_MEMORY_URL);
+ properties.setProperty(JDBC_DRIVER, Configuration.JDBC_IN_MEMROY_DRIVER);
+ properties.setProperty(DDL_GENERATION, DROP_AND_CREATE);
+ properties.setProperty(THROW_EXCEPTIONS, "true");
+ case REMOTE:
+ properties.setProperty(JDBC_URL, configuration.getDatabaseUrl());
+ properties.setProperty(JDBC_DRIVER, configuration.getDatabaseDriver());
+ break;
+ case LOCAL:
+ properties.setProperty(JDBC_URL, configuration.getLocalDatabaseUrl());
+ properties.setProperty(JDBC_DRIVER, Configuration.JDBC_LOCAL_DRIVER);
+ break;
+ }
+ return properties;
+ }
+
+
+ // ----- AbstractModule ----------------------------------------------------
+
@Override
protected void configure() {
installFactories();
@@ -154,64 +199,41 @@ public class ControllerModule extends AbstractModule {
requestStaticInjection(ExecutionCommandWrapper.class);
}
+
+ // ----- helper methods ----------------------------------------------------
+
private PersistModule buildJpaPersistModule() {
PersistenceType persistenceType = configuration.getPersistenceType();
AmbariJpaPersistModule jpaPersistModule = new AmbariJpaPersistModule(Configuration.JDBC_UNIT_NAME);
- Properties properties = new Properties();
-
- // custom jdbc properties
- Map<String, String> custom = configuration.getDatabaseCustomProperties();
-
- if (0 != custom.size()) {
- for (Entry<String, String> entry : custom.entrySet()) {
- properties.setProperty("eclipselink.jdbc.property." + entry.getKey(),
- entry.getValue());
+ Properties persistenceProperties = getPersistenceProperties(configuration);
+
+ if (!persistenceType.equals(PersistenceType.IN_MEMORY)) {
+ persistenceProperties.setProperty(JDBC_USER, configuration.getDatabaseUser());
+ persistenceProperties.setProperty(JDBC_PASSWORD, configuration.getDatabasePassword());
+
+ switch (configuration.getJPATableGenerationStrategy()) {
+ case CREATE:
+ persistenceProperties.setProperty(DDL_GENERATION, CREATE_ONLY);
+ dbInitNeeded = true;
+ break;
+ case DROP_AND_CREATE:
+ persistenceProperties.setProperty(DDL_GENERATION, DROP_AND_CREATE);
+ dbInitNeeded = true;
+ break;
+ case CREATE_OR_EXTEND:
+ persistenceProperties.setProperty(DDL_GENERATION, CREATE_OR_EXTEND);
+ break;
+ default:
+ break;
}
- }
-
- switch (persistenceType) {
- case IN_MEMORY:
- properties.setProperty(JDBC_URL, Configuration.JDBC_IN_MEMORY_URL);
- properties.setProperty(JDBC_DRIVER, Configuration.JDBC_IN_MEMROY_DRIVER);
- properties.setProperty(DDL_GENERATION, DROP_AND_CREATE);
- properties.setProperty(THROW_EXCEPTIONS, "true");
- jpaPersistModule.properties(properties);
- return jpaPersistModule;
- case REMOTE:
- properties.setProperty(JDBC_URL, configuration.getDatabaseUrl());
- properties.setProperty(JDBC_DRIVER, configuration.getDatabaseDriver());
- break;
- case LOCAL:
- properties.setProperty(JDBC_URL, configuration.getLocalDatabaseUrl());
- properties.setProperty(JDBC_DRIVER, Configuration.JDBC_LOCAL_DRIVER);
- break;
- }
-
- properties.setProperty(JDBC_USER, configuration.getDatabaseUser());
- properties.setProperty(JDBC_PASSWORD, configuration.getDatabasePassword());
- switch (configuration.getJPATableGenerationStrategy()) {
- case CREATE:
- properties.setProperty(DDL_GENERATION, CREATE_ONLY);
- dbInitNeeded = true;
- break;
- case DROP_AND_CREATE:
- properties.setProperty(DDL_GENERATION, DROP_AND_CREATE);
- dbInitNeeded = true;
- break;
- case CREATE_OR_EXTEND:
- properties.setProperty(DDL_GENERATION, CREATE_OR_EXTEND);
- break;
- default:
- break;
+ persistenceProperties.setProperty(DDL_GENERATION_MODE, DDL_BOTH_GENERATION);
+ persistenceProperties.setProperty(CREATE_JDBC_DDL_FILE, "DDL-create.jdbc");
+ persistenceProperties.setProperty(DROP_JDBC_DDL_FILE, "DDL-drop.jdbc");
}
- properties.setProperty(DDL_GENERATION_MODE, DDL_BOTH_GENERATION);
- properties.setProperty(CREATE_JDBC_DDL_FILE, "DDL-create.jdbc");
- properties.setProperty(DROP_JDBC_DDL_FILE, "DDL-drop.jdbc");
-
- jpaPersistModule.properties(properties);
+ jpaPersistModule.properties(persistenceProperties);
return jpaPersistModule;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java
index e554973..13f7b04 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java
@@ -76,7 +76,7 @@ public class ViewDAO {
/**
* Make an instance managed and persistent.
*
- * @param ViewEntity entity to persist
+ * @param ViewEntity entity to store
*/
@Transactional
public void create(ViewEntity ViewEntity) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
index b01ab36..a133ad2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
@@ -89,7 +89,7 @@ public class ViewEntity {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
private Collection<ViewResourceEntity> resources = new HashSet<ViewResourceEntity>();
- /**
+ /**
* The list of view instances.
*/
@OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
@@ -356,6 +356,15 @@ public class ViewEntity {
}
/**
+ * Get the Ambari configuration.
+ *
+ * @return the Ambari configuration
+ */
+ public Configuration getAmbariConfiguration() {
+ return ambariConfiguration;
+ }
+
+ /**
* Get a resource name qualified by the associated view name.
*
* @param resourceTypeName the resource type name
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntityEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntityEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntityEntity.java
new file mode 100644
index 0000000..cae57fc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntityEntity.java
@@ -0,0 +1,187 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+/**
+ * Represents an entity of a View.
+ */
+@Table(name = "viewentity")
+@Entity
+@TableGenerator(name = "viewentity_id_generator",
+ table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "value"
+ , pkColumnValue = "viewentity_id_seq"
+ , initialValue = 1
+ , allocationSize = 50
+)public class ViewEntityEntity {
+
+ @Column(name = "id")
+ @Id
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "viewentity_id_generator")
+ private Long id;
+
+ /**
+ * The view name.
+ */
+ @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+ private String viewName;
+
+ @Column(name = "view_instance_name", nullable = false, insertable = false, updatable = false)
+ private String viewInstanceName;
+
+ /**
+ * The entity class name.
+ */
+ @Column(name = "class_name", nullable = false)
+ @Basic
+ private String className;
+
+ /**
+ * The id property of the entity.
+ */
+ @Column(name = "id_property")
+ @Basic
+ private String idProperty;
+
+
+ @ManyToOne
+ @JoinColumns({
+ @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false),
+ @JoinColumn(name = "view_instance_name", referencedColumnName = "name", nullable = false)
+ })
+ private ViewInstanceEntity viewInstance;
+
+
+ // ----- ViewEntityEntity ------------------------------------------------
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * Get the view name.
+ *
+ * @return the view name
+ */
+ public String getViewName() {
+ return viewName;
+ }
+
+ /**
+ * Set the view name
+ *
+ * @param viewName the view name
+ */
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+
+ public String getViewInstanceName() {
+ return viewInstanceName;
+ }
+
+ public void setViewInstanceName(String viewInstanceName) {
+ this.viewInstanceName = viewInstanceName;
+ }
+
+ /**
+ * Get the entity class name.
+ *
+ * @return the entity class name
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Set the entity class name.
+ *
+ * @param name the entity class name
+ */
+ public void setClassName(String name) {
+ this.className = name;
+ }
+
+ /**
+ * Get the id property.
+ *
+ * @return the id property
+ */
+ public String getIdProperty() {
+ return idProperty;
+ }
+
+ /**
+ * Set the id property.
+ *
+ * @param idProperty the id property
+ */
+ public void setIdProperty(String idProperty) {
+ this.idProperty = idProperty;
+ }
+
+ public ViewInstanceEntity getViewInstance() {
+ return viewInstance;
+ }
+
+ public void setViewInstance(ViewInstanceEntity viewInstance) {
+ this.viewInstance = viewInstance;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ViewEntityEntity that = (ViewEntityEntity) o;
+
+ if (!className.equals(that.className)) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (idProperty != null ? !idProperty.equals(that.idProperty) : that.idProperty != null) return false;
+ if (!viewInstanceName.equals(that.viewInstanceName)) return false;
+ if (!viewName.equals(that.viewName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + viewName.hashCode();
+ result = 31 * result + viewInstanceName.hashCode();
+ result = 31 * result + className.hashCode();
+ result = 31 * result + (idProperty != null ? idProperty.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
index 901ce09..c6557f2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
@@ -74,6 +74,12 @@ public class ViewInstanceEntity {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "viewInstance")
private Collection<ViewInstanceDataEntity> data = new HashSet<ViewInstanceDataEntity>();
+ /**
+ * The list of view entities.
+ */
+ @OneToMany(cascade = CascadeType.ALL, mappedBy = "viewInstance")
+ private Collection<ViewEntityEntity> entities = new HashSet<ViewEntityEntity>();
+
@ManyToOne
@JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false)
private ViewEntity view;
@@ -270,6 +276,24 @@ public class ViewInstanceEntity {
}
/**
+ * Get the view entities.
+ *
+ * @return the view entities
+ */
+ public Collection<ViewEntityEntity> getEntities() {
+ return entities;
+ }
+
+ /**
+ * Set the view entities.
+ *
+ * @param entities the view entities
+ */
+ public void setEntities(Collection<ViewEntityEntity> entities) {
+ this.entities = entities;
+ }
+
+ /**
* Get the view instance application data.
*
* @return the view instance application data map
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog160.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog160.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog160.java
index b0521ee..fb4a87a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog160.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog160.java
@@ -21,6 +21,7 @@ package org.apache.ambari.server.upgrade;
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.DBAccessor;
import java.sql.SQLException;
@@ -56,6 +57,16 @@ public class UpgradeCatalog160 extends AbstractUpgradeCatalog {
dbAccessor.createTable("hostgroup_configuration", columns, "blueprint_name",
"hostgroup_name", "type_name");
+ // View entity
+ columns = new ArrayList<DBAccessor.DBColumnInfo>();
+ columns.add(new DBAccessor.DBColumnInfo("id", Long.class, null, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("view_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("view_instance_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("class_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("id_property", String.class, 255, null, true));
+
+ dbAccessor.createTable("viewentity", columns, "id");
+
//=========================================================================
// Add columns
dbAccessor.addColumn("hostcomponentdesiredstate",
@@ -67,6 +78,9 @@ public class UpgradeCatalog160 extends AbstractUpgradeCatalog {
"blueprint_name", "hostgroup", "blueprint_name", true);
dbAccessor.addFKConstraint("hostgroup_configuration", "FK_hg_config_hostgroup_name",
"hostgroup_name", "hostgroup", "name", true);
+ dbAccessor.addFKConstraint("viewentity", "FK_viewentity_view_name",
+ new String[]{"view_name", "view_instance_name"}, "viewinstance", new String[]{"view_name", "name"}, true);
+
}
@@ -74,6 +88,16 @@ public class UpgradeCatalog160 extends AbstractUpgradeCatalog {
@Override
protected void executeDMLUpdates() throws AmbariException, SQLException {
+ String dbType = getDbType();
+
+ //add new sequences for view entity
+ String valueColumnName = "\"value\"";
+ if (Configuration.ORACLE_DB_NAME.equals(dbType) || Configuration.MYSQL_DB_NAME.equals(dbType)) {
+ valueColumnName = "value";
+ }
+
+ dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, " + valueColumnName + ") " +
+ "VALUES('viewentity_id_seq', 0)", true);
}
@Override
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
index e4cc71f..862e2e1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
@@ -18,8 +18,13 @@
package org.apache.ambari.server.view;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.view.persistence.DataStoreImpl;
+import org.apache.ambari.server.view.persistence.DataStoreModule;
+import org.apache.ambari.view.DataStore;
import org.apache.ambari.view.ResourceProvider;
import org.apache.ambari.view.URLStreamProvider;
import org.apache.ambari.view.ViewContext;
@@ -55,6 +60,11 @@ public class ViewContextImpl implements ViewContext {
*/
private final URLStreamProvider streamProvider;
+ /**
+ * The data store.
+ */
+ private DataStore dataStore = null;
+
// ---- Constructors -------------------------------------------------------
@@ -139,6 +149,15 @@ public class ViewContextImpl implements ViewContext {
return streamProvider;
}
+ @Override
+ public synchronized DataStore getDataStore() {
+ if (dataStore == null) {
+ Injector injector = Guice.createInjector(new DataStoreModule(viewInstanceEntity));
+ dataStore = injector.getInstance(DataStoreImpl.class);
+ }
+ return dataStore;
+ }
+
// ----- Inner class : ViewURLStreamProvider -------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index a5112e0..49fa406 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -32,10 +32,12 @@ import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.orm.dao.ViewDAO;
import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
import org.apache.ambari.server.orm.entities.ViewParameterEntity;
import org.apache.ambari.server.orm.entities.ViewResourceEntity;
+import org.apache.ambari.server.view.configuration.EntityConfig;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.server.view.configuration.ParameterConfig;
import org.apache.ambari.server.view.configuration.PropertyConfig;
@@ -277,7 +279,7 @@ public class ViewRegistry {
viewInstanceDefinition.putProperty(propertyConfig.getKey(), propertyConfig.getValue());
}
- _installViewInstance(viewDefinition, viewInstanceDefinition);
+ installViewInstance(viewDefinition, viewInstanceDefinition);
instanceDefinitions.add(viewInstanceDefinition);
}
} catch (Exception e) {
@@ -313,7 +315,7 @@ public class ViewRegistry {
}
instanceDAO.create(instanceEntity);
try {
- _installViewInstance(viewEntity, instanceEntity);
+ installViewInstance(viewEntity, instanceEntity);
} catch (ClassNotFoundException e) {
LOG.error("Caught exception installing view instance.", e);
}
@@ -485,8 +487,8 @@ public class ViewRegistry {
}
// install a view instance definition
- private void _installViewInstance(ViewEntity viewDefinition,
- ViewInstanceEntity viewInstanceDefinition)
+ private void installViewInstance(ViewEntity viewDefinition,
+ ViewInstanceEntity viewInstanceDefinition)
throws ClassNotFoundException {
ViewContext viewInstanceContext = new ViewContextImpl(viewInstanceDefinition, this);
@@ -518,10 +520,32 @@ public class ViewRegistry {
}
}
+ setPersistenceEntities(viewInstanceDefinition);
+
viewDefinition.addInstanceDefinition(viewInstanceDefinition);
addInstanceDefinition(viewDefinition, viewInstanceDefinition);
}
+ // Set the entities defined in the view persistence element for the given view instance
+ private static void setPersistenceEntities(ViewInstanceEntity viewInstanceDefinition) {
+ ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
+ Collection<ViewEntityEntity> entities = new HashSet<ViewEntityEntity>();
+
+ ViewConfig viewConfig = viewDefinition.getConfiguration();
+ for (EntityConfig entityConfiguration : viewConfig.getPersistence().getEntities()) {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+
+ viewEntityEntity.setViewName(viewDefinition.getName());
+ viewEntityEntity.setViewInstanceName(viewInstanceDefinition.getName());
+ viewEntityEntity.setClassName(entityConfiguration.getClassName());
+ viewEntityEntity.setIdProperty(entityConfiguration.getIdProperty());
+ viewEntityEntity.setViewInstance(viewInstanceDefinition);
+
+ entities.add(viewEntityEntity);
+ }
+ viewInstanceDefinition.setEntities(entities);
+ }
+
// get the given service class from the given class loader; inject a handler and context
private static <T> T getService(Class<T> clazz,
final ViewResourceHandler viewResourceHandler,
@@ -561,8 +585,6 @@ public class ViewRegistry {
for (ViewEntity viewEntity : viewDAO.findAll()) {
String name = viewEntity.getName();
if (!ViewRegistry.getInstance().viewDefinitions.containsKey(name)) {
-
- System.out.println("removing view " + name);
viewDAO.remove(viewEntity);
} else {
persistedViews.add(name);
@@ -573,12 +595,13 @@ public class ViewRegistry {
ViewInstanceEntity instanceEntity = viewDefinition.getInstanceDefinition(viewInstanceEntity.getName());
if (instanceEntity == null) {
viewInstanceEntity.setViewEntity(viewDefinition);
- _installViewInstance(viewDefinition, viewInstanceEntity);
+ installViewInstance(viewDefinition, viewInstanceEntity);
instanceDefinitions.add(viewInstanceEntity);
} else {
// apply overrides to the in-memory view instance entities
instanceEntity.setData(viewInstanceEntity.getData());
instanceEntity.setProperties(viewInstanceEntity.getProperties());
+ instanceEntity.setEntities(viewInstanceEntity.getEntities());
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/EntityConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/EntityConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/EntityConfig.java
new file mode 100644
index 0000000..f2f5e96
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/EntityConfig.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.view.configuration;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * View persistence entity configuration.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class EntityConfig {
+
+ @XmlElement(name="class")
+ private String className;
+
+ @XmlElement(name="id-property")
+ private String idProperty;
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getIdProperty() {
+ return idProperty;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PersistenceConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PersistenceConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PersistenceConfig.java
new file mode 100644
index 0000000..77ad4ef
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PersistenceConfig.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.view.configuration;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * View persistence configuration.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PersistenceConfig {
+ /**
+ * The persistence entities.
+ */
+ @XmlElement(name="entity")
+ private List<EntityConfig> entities;
+
+ /**
+ * Get the entity configurations.
+ *
+ * @return the entity configurations
+ */
+ public List<EntityConfig> getEntities() {
+ return entities == null ? Collections.<EntityConfig>emptyList() : entities;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
index 8020bc0..17d2619 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
@@ -68,6 +68,12 @@ public class ViewConfig {
private List<InstanceConfig> instances;
/**
+ * The view persistence configuration.
+ */
+ @XmlElement(name="persistence")
+ private PersistenceConfig persistence;
+
+ /**
* Get the unique name.
*
* @return the view name
@@ -120,4 +126,13 @@ public class ViewConfig {
public List<InstanceConfig> getInstances() {
return instances == null ? Collections.<InstanceConfig>emptyList() : instances;
}
+
+ /**
+ * Get the view persistence configuration.
+ *
+ * @return the view persistence configuration
+ */
+ public PersistenceConfig getPersistence() {
+ return persistence;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java
new file mode 100644
index 0000000..6b4cc76
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java
@@ -0,0 +1,603 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.persistence;
+
+import org.apache.ambari.server.orm.entities.ViewEntityEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.view.DataStore;
+import org.apache.ambari.view.PersistenceException;
+import org.eclipse.persistence.dynamic.DynamicClassLoader;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicTypeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+
+/**
+ * A data store implementation that uses dynamic JPA entities to
+ * persist view entities to the Ambari database.
+ */
+public class DataStoreImpl implements DataStore {
+
+ /**
+ * JPA entity manager
+ */
+ @Inject
+ EntityManagerFactory entityManagerFactory;
+
+ /**
+ * The dynamic class loader.
+ */
+ @Inject
+ DynamicClassLoader classLoader;
+
+ /**
+ * The dynamic helper.
+ */
+ @Inject
+ JPADynamicHelper jpaDynamicHelper;
+
+ /**
+ * A factory to get a schema manager.
+ */
+ @Inject
+ SchemaManagerFactory schemaManagerFactory;
+
+ /**
+ * The view instance.
+ */
+ @Inject
+ ViewInstanceEntity viewInstanceEntity;
+
+ /**
+ * Map of dynamic entity names keyed by view entity class.
+ */
+ private final Map<Class, String> entityClassMap = new HashMap<Class, String>();
+
+ /**
+ * Map of entity primary key fields keyed by dynamic entity name.
+ */
+ private final Map<String, ViewEntityEntity> entityMap = new HashMap<String, ViewEntityEntity>();
+
+ /**
+ * Map of dynamic entity type builders keyed by dynamic entity name.
+ */
+ private final Map<String, JPADynamicTypeBuilder> typeBuilderMap = new HashMap<String, JPADynamicTypeBuilder>();
+
+ /**
+ * Indicates whether or not the data store has been initialized.
+ */
+ private volatile boolean initialized = false;
+
+ /**
+ * The logger.
+ */
+ protected final static Logger LOG = LoggerFactory.getLogger(DataStoreImpl.class);
+
+
+ // ----- DataStore ---------------------------------------------------------
+
+ @Override
+ public void store(Object entity) throws PersistenceException {
+ checkInitialize();
+
+ EntityManager em = getEntityManager();
+ try {
+ em.getTransaction().begin();
+ try {
+ persistEntity(entity, em, new HashSet<DynamicEntity>());
+ em.getTransaction().commit();
+ } catch (Exception e) {
+ if (em.getTransaction()!= null) {
+ em.getTransaction().rollback();
+ }
+ throwPersistenceException("Caught exception trying to store view entity " + entity, e);
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ @Override
+ public void remove(Object entity) throws PersistenceException {
+ checkInitialize();
+
+ EntityManager em = getEntityManager();
+ try {
+ Class clazz = entity.getClass();
+ String id = getIdFieldName(clazz);
+ DynamicType type = getDynamicEntityType(clazz);
+
+ if (type != null) {
+ try {
+ Map<String, Object> properties = getEntityProperties(entity);
+ DynamicEntity dynamicEntity = em.getReference(type.getJavaClass(), properties.get(id));
+
+ if (dynamicEntity != null) {
+ em.getTransaction().begin();
+ try {
+ em.remove(dynamicEntity);
+ em.getTransaction().commit();
+ } catch (Exception e) {
+ if (em.getTransaction()!= null) {
+ em.getTransaction().rollback();
+ }
+ throwPersistenceException("Caught exception trying to remove view entity " + entity, e);
+ }
+ }
+
+ } catch (Exception e) {
+ throwPersistenceException("Caught exception trying to remove view entity " + entity, e);
+ }
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ @Override
+ public <T> T find(Class<T> clazz, Object primaryKey) throws PersistenceException {
+ checkInitialize();
+
+ EntityManager em = getEntityManager();
+ try {
+ DynamicEntity dynamicEntity = null;
+ DynamicType type = getDynamicEntityType(clazz);
+
+ if (type != null) {
+ dynamicEntity = em.find(type.getJavaClass(), primaryKey);
+ }
+ return dynamicEntity == null ? null : toEntity(clazz, type, dynamicEntity);
+ } catch (Exception e) {
+ throwPersistenceException("Caught exception trying to find " +
+ clazz.getName() + " where key=" + primaryKey, e);
+ } finally {
+ em.close();
+ }
+ return null;
+ }
+
+ @Override
+ public <T> Collection<T> findAll(Class<T> clazz, String whereClause) throws PersistenceException {
+ checkInitialize();
+
+ EntityManager em = getEntityManager();
+ try {
+ Collection<T> resources = new HashSet<T>();
+ DynamicType type = getDynamicEntityType(clazz);
+
+ if (type != null) {
+ try {
+ Query query = em.createQuery(getSelectStatement(clazz, whereClause));
+
+ List dynamicEntities = query.getResultList();
+
+ for (Object dynamicEntity : dynamicEntities) {
+ resources.add(toEntity(clazz, type, (DynamicEntity) dynamicEntity));
+ }
+ } catch (Exception e) {
+ throwPersistenceException("Caught exception trying to find " +
+ clazz.getName() + " where " + whereClause, e);
+ }
+ }
+ return resources;
+ } finally {
+ em.close();
+ }
+ }
+
+
+ // ----- helper methods ----------------------------------------------------
+
+ // lazy initialize the data store
+ private void checkInitialize() throws PersistenceException {
+ if (!initialized) {
+ synchronized (this) {
+ if (!initialized) {
+ initialized = true;
+ try {
+ for (ViewEntityEntity viewEntityEntity : viewInstanceEntity.getEntities()){
+
+ String className = viewEntityEntity.getClassName();
+ Class clazz = classLoader.loadClass(className);
+ String name = getEntityName(viewEntityEntity);
+
+ entityMap.put(name, viewEntityEntity);
+ entityClassMap.put(clazz, name);
+ }
+
+ configureTypes(jpaDynamicHelper, classLoader);
+
+ } catch (Exception e) {
+ throwPersistenceException("Can't initialize data store for view " +
+ viewInstanceEntity.getViewName() + "." + viewInstanceEntity.getName(), e);
+ }
+ }
+ }
+ }
+ }
+
+ // configure the dynamic types for the entities defined for the associated view
+ private void configureTypes(JPADynamicHelper helper, DynamicClassLoader dcl)
+ throws IntrospectionException, PersistenceException, NoSuchFieldException {
+
+ // create a dynamic type builder for each declared view entity type
+ for (Map.Entry<Class, String> entry: entityClassMap.entrySet()) {
+ String entityName = entry.getValue();
+ Class<?> javaType = dcl.createDynamicClass(entityName);
+ String tableName = getTableName(entityMap.get(entityName));
+
+ JPADynamicTypeBuilder typeBuilder = new JPADynamicTypeBuilder(javaType, null, tableName);
+ typeBuilderMap.put(entityName, typeBuilder);
+ }
+
+ // add the direct mapped properties to the dynamic type builders
+ for (Map.Entry<Class, String> entry: entityClassMap.entrySet()) {
+
+ Class clazz = entry.getKey();
+ String entityName = entry.getValue();
+ JPADynamicTypeBuilder typeBuilder = typeBuilderMap.get(entityName);
+
+ Map<String, PropertyDescriptor> descriptorMap = getDescriptorMap(clazz);
+
+ for (Map.Entry<String, PropertyDescriptor> descriptorEntry : descriptorMap.entrySet()) {
+ String propertyName = descriptorEntry.getKey();
+ PropertyDescriptor descriptor = descriptorEntry.getValue();
+
+ if (propertyName.equals(entityMap.get(entityName).getIdProperty())) {
+ typeBuilder.setPrimaryKeyFields(propertyName);
+ }
+
+ Class<?> propertyType = descriptor.getPropertyType();
+
+ if (isDirectMappingType(propertyType)) {
+ typeBuilder.addDirectMapping(propertyName, propertyType, propertyName);
+ }
+ }
+ }
+
+ // add the relationships to the dynamic type builders
+ for (Map.Entry<Class, String> entry: entityClassMap.entrySet()) {
+
+ Class clazz = entry.getKey();
+ String entityName = entry.getValue();
+ JPADynamicTypeBuilder typeBuilder = typeBuilderMap.get(entityName);
+
+ Map<String, PropertyDescriptor> descriptorMap = getDescriptorMap(clazz);
+
+ for (Map.Entry<String, PropertyDescriptor> descriptorEntry : descriptorMap.entrySet()) {
+ String propertyName = descriptorEntry.getKey();
+ PropertyDescriptor descriptor = descriptorEntry.getValue();
+ if (propertyName.equals(entityMap.get(entityName).getIdProperty())) {
+ typeBuilder.setPrimaryKeyFields(propertyName);
+ }
+
+ Class<?> propertyType = descriptor.getPropertyType();
+ String refEntityName = entityClassMap.get(propertyType);
+
+ if (refEntityName == null) {
+ if (Collection.class.isAssignableFrom(propertyType)) {
+
+ String tableName = getTableName(entityMap.get(entityName)) + "_" + propertyName;
+
+ Class<?> parameterizedTypeClass = getParameterizedTypeClass(clazz, propertyName);
+
+ refEntityName = entityClassMap.get(parameterizedTypeClass);
+
+ if (refEntityName == null) {
+ typeBuilder.addDirectCollectionMapping(propertyName, tableName, propertyName,
+ parameterizedTypeClass, entityMap.get(entityName).getIdProperty());
+ } else {
+ DynamicType refType = typeBuilderMap.get(refEntityName).getType();
+ typeBuilder.addManyToManyMapping(propertyName, refType, tableName);
+ }
+ }
+ } else {
+ DynamicType refType = typeBuilderMap.get(refEntityName).getType();
+ typeBuilder.addOneToOneMapping(propertyName, refType, propertyName);
+ }
+ }
+ }
+
+ DynamicType[] types = new DynamicType[ typeBuilderMap.size()];
+ int i = typeBuilderMap.size() - 1;
+ for (JPADynamicTypeBuilder typeBuilder : typeBuilderMap.values()) {
+ types[i--] = typeBuilder.getType();
+ }
+ helper.addTypes(true, true, types);
+
+ // extend the tables if needed (i.e. attribute added to the view entity)
+ schemaManagerFactory.getSchemaManager(helper.getSession()).extendDefaultTables(true);
+ }
+
+ // persist the given view entity to the entity manager and
+ // return the corresponding dynamic entity
+ private DynamicEntity persistEntity(Object entity, EntityManager em, Set<DynamicEntity> persistSet)
+ throws PersistenceException, IntrospectionException, InvocationTargetException,
+ IllegalAccessException, NoSuchFieldException {
+ DynamicEntity dynamicEntity = null;
+ Class clazz = entity.getClass();
+ String id = getIdFieldName(clazz);
+
+ Map<String, Object> properties = getEntityProperties(entity);
+
+ DynamicType type = getDynamicEntityType(clazz);
+
+ if (type != null) {
+ dynamicEntity = em.find(type.getJavaClass(), properties.get(id));
+
+ boolean create = dynamicEntity == null;
+
+ if (create) {
+ dynamicEntity = type.newDynamicEntity();
+ }
+
+ // has this entity already been accounted for?
+ if (persistSet.contains(dynamicEntity)) {
+ return dynamicEntity;
+ }
+
+ persistSet.add(dynamicEntity);
+
+ for (String propertyName : type.getPropertiesNames()) {
+ if (properties.containsKey(propertyName)) {
+ Object value = properties.get(propertyName);
+ if (value != null) {
+ Class<?> valueClass = value.getClass();
+
+ if (Collection.class.isAssignableFrom(valueClass)) {
+
+ Class<?> typeClass = getParameterizedTypeClass(clazz, propertyName);
+ Collection<Object> collection = dynamicEntity.get(propertyName);
+
+ collection.clear();
+
+ for (Object collectionValue : (Collection) value) {
+
+ if (getDynamicEntityType(typeClass)!= null ) {
+ collectionValue = persistEntity(collectionValue, em, persistSet);
+ }
+ if (collectionValue != null) {
+ collection.add(collectionValue);
+ }
+ }
+ } else {
+ if (getDynamicEntityType(valueClass)!= null ) {
+ value = persistEntity(value, em, persistSet);
+ }
+ if (value != null) {
+ dynamicEntity.set(propertyName, value);
+ }
+ }
+ }
+ }
+ }
+
+ if (create) {
+ em.persist(dynamicEntity);
+ }
+ }
+ return dynamicEntity;
+ }
+
+ // convert the given dynamic entity to a view entity
+ private <T> T toEntity(Class<T> clazz, DynamicType type, DynamicEntity entity)
+ throws IntrospectionException, InvocationTargetException,
+ IllegalAccessException, InstantiationException, NoSuchFieldException {
+ T resource = clazz.newInstance();
+
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ for (String propertyName : type.getPropertiesNames()) {
+ properties.put(propertyName, entity.get(propertyName));
+ }
+ setEntityProperties(resource, properties);
+
+ return resource;
+ }
+
+ // build a JPA select statement from the given view entity class and where clause
+ private <T> String getSelectStatement(Class<T> clazz, String whereClause)
+ throws IntrospectionException {
+ StringBuilder stringBuilder = new StringBuilder();
+ String entityName = entityClassMap.get(clazz);
+
+ stringBuilder.append("SELECT e FROM ").append(entityName).append(" e");
+ if (whereClause != null) {
+ stringBuilder.append(" WHERE");
+
+ Set<String> propertyNames = getPropertyNames(clazz);
+ StringTokenizer tokenizer = new StringTokenizer(whereClause, " \t\n\r\f+-*/=><()\"", true);
+ boolean quoted = false;
+
+ while (tokenizer.hasMoreElements()) {
+ String token = tokenizer.nextToken();
+
+ quoted = quoted ^ token.equals("\"");
+
+ if (propertyNames.contains(token) && !quoted) {
+ stringBuilder.append(" e.").append(token);
+ } else {
+ stringBuilder.append(token);
+ }
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+ // get a map of properties from the given view entity
+ private Map<String, Object> getEntityProperties(Object entity)
+ throws IntrospectionException, InvocationTargetException, IllegalAccessException {
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(entity.getClass()).getPropertyDescriptors()) {
+ String name = pd.getName();
+ Method readMethod = pd.getReadMethod();
+ if (readMethod != null) {
+ properties.put(name, readMethod.invoke(entity));
+ }
+ }
+ return properties;
+ }
+
+ // set the properties on the given view entity from the given map of properties; convert all
+ // DynamicEntity values to their associated view entity types
+ private void setEntityProperties(Object entity, Map<String, Object> properties)
+ throws IntrospectionException, InvocationTargetException, IllegalAccessException,
+ InstantiationException, NoSuchFieldException {
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(entity.getClass()).getPropertyDescriptors()) {
+ String name = pd.getName();
+ if (properties.containsKey(name)) {
+
+ Method writeMethod = pd.getWriteMethod();
+ if (writeMethod != null) {
+
+ Object value = properties.get(name);
+
+ if (value instanceof Collection) {
+ Set<Object> newCollection = new HashSet<Object>();
+
+ for (Object collectionValue: (Collection)value) {
+
+ if (collectionValue instanceof DynamicEntity) {
+
+ Class<?> clazz = entity.getClass();
+ Class<?> parameterizedTypeClass = getParameterizedTypeClass(clazz, pd.getName());
+
+ collectionValue = toEntity(parameterizedTypeClass,
+ getDynamicEntityType(parameterizedTypeClass), (DynamicEntity) collectionValue);
+ }
+ if ( collectionValue != null) {
+ newCollection.add(collectionValue);
+ }
+ }
+ writeMethod.invoke(entity, newCollection);
+ } else {
+ if (value instanceof DynamicEntity) {
+
+ Class<?> clazz = pd.getPropertyType();
+
+ value = toEntity(clazz, getDynamicEntityType(clazz), (DynamicEntity) value);
+ }
+ if ( value != null) {
+ writeMethod.invoke(entity, value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // determine whether or not a property of the given type should be a direct mapping in the dynamic entity
+ private boolean isDirectMappingType(Class<?> propertyType) {
+ return !Collection.class.isAssignableFrom(propertyType) && entityClassMap.get(propertyType) == null;
+ }
+
+ // get the dynamic entity type from the given view entity class
+ private DynamicType getDynamicEntityType(Class clazz) {
+ JPADynamicTypeBuilder builder = typeBuilderMap.get(entityClassMap.get(clazz));
+
+ return builder == null ? null : builder.getType();
+ }
+
+ // get the id field name for the given view entity class
+ private String getIdFieldName(Class clazz) throws PersistenceException {
+ if (entityClassMap.containsKey(clazz)){
+ String entityName = entityClassMap.get(clazz);
+ if (entityMap.containsKey(entityName)) {
+ return entityMap.get(entityName).getIdProperty();
+ }
+ }
+ throw new PersistenceException("The class " + clazz.getName() + "is not registered as an entity.");
+ }
+
+ // get a descriptor map for the given bean class
+ private static Map<String, PropertyDescriptor> getDescriptorMap(Class<?> clazz) throws IntrospectionException {
+ Map<String, PropertyDescriptor> descriptorMap = new HashMap<String, PropertyDescriptor>();
+
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(clazz).getPropertyDescriptors()) {
+ String name = pd.getName();
+ if (pd.getReadMethod() != null && !name.equals("class")) {
+ descriptorMap.put(name, pd);
+ }
+ }
+ return descriptorMap;
+ }
+
+ // get the property names for the given view entity class
+ private static Set<String> getPropertyNames(Class clazz) throws IntrospectionException {
+ Set<String> propertyNames = new HashSet<String>();
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(clazz).getPropertyDescriptors()) {
+ propertyNames.add(pd.getName());
+ }
+ return propertyNames;
+ }
+
+ // get the parameterized type class for the given field of the given class
+ private static Class<?> getParameterizedTypeClass(Class clazz, String fieldName) throws NoSuchFieldException {
+ Field field = clazz.getDeclaredField(fieldName);
+ ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
+ return (Class<?>) parameterizedType.getActualTypeArguments()[0];
+ }
+
+ // throw a new persistence exception and log the error
+ private static void throwPersistenceException(String msg, Exception e) throws PersistenceException {
+ LOG.error(msg, e);
+ throw new PersistenceException(msg, e);
+ }
+
+ // get a table name for the given view entity
+ private static String getTableName(ViewEntityEntity entity) {
+ return (getEntityName(entity)).toUpperCase();
+ }
+
+ // get a dynamic entity name for the given view entity
+ private static String getEntityName(ViewEntityEntity entity) {
+ String className = entity.getClassName();
+ String[] parts = className.split("\\.");
+
+ return parts[parts.length - 1] + entity.getId();
+ }
+
+ // get an entity manager
+ private EntityManager getEntityManager() {
+ return entityManagerFactory.createEntityManager();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreModule.java b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreModule.java
new file mode 100644
index 0000000..a995868
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreModule.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.persistence;
+
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.orm.PersistenceType;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.dynamic.DynamicClassLoader;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.tools.schemaframework.SchemaManager;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Map;
+
+import static org.eclipse.persistence.config.PersistenceUnitProperties.JDBC_PASSWORD;
+import static org.eclipse.persistence.config.PersistenceUnitProperties.JDBC_USER;
+
+/**
+ * Module used for data store creation and injection.
+ */
+public class DataStoreModule implements Module, SchemaManagerFactory {
+
+ /**
+ * The view instance.
+ */
+ private final ViewInstanceEntity viewInstanceEntity;
+
+ /**
+ * The class loader.
+ */
+ private final DynamicClassLoader classLoader;
+
+ /**
+ * The entity manager factory.
+ */
+ private final EntityManagerFactory entityManagerFactory;
+
+ /**
+ * The dynamic JPA helper.
+ */
+ private final JPADynamicHelper jpaDynamicHelper;
+
+ /**
+ * View persistence unit name.
+ */
+ private static final String VIEWS_PERSISTENCE_UNIT_NAME = "ambari-views";
+
+
+ // ----- Constructors ------------------------------------------------------
+
+ public DataStoreModule(ViewInstanceEntity viewInstanceEntity) {
+ ViewEntity view = viewInstanceEntity.getViewEntity();
+
+ this.viewInstanceEntity = viewInstanceEntity;
+ this.classLoader = new DynamicClassLoader(view.getClassLoader());
+ this.entityManagerFactory = getEntityManagerFactory(view.getAmbariConfiguration());
+ this.jpaDynamicHelper = new JPADynamicHelper(entityManagerFactory.createEntityManager());
+ }
+
+
+ // ----- Module ------------------------------------------------------------
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(ViewInstanceEntity.class).toInstance(viewInstanceEntity);
+ binder.bind(DynamicClassLoader.class).toInstance(classLoader);
+ binder.bind(EntityManagerFactory.class).toInstance(entityManagerFactory);
+ binder.bind(JPADynamicHelper.class).toInstance(jpaDynamicHelper);
+ binder.bind(SchemaManagerFactory.class).toInstance(this);
+ }
+
+
+ // ----- SchemaManagerFactory ----------------------------------------------
+
+ @Override
+ public SchemaManager getSchemaManager(DatabaseSession session) {
+ return new SchemaManager(session);
+ }
+
+
+ // ----- helper methods ----------------------------------------------------
+
+ // get an entity manager factory for the given class loader and configuration
+ private EntityManagerFactory getEntityManagerFactory(Configuration configuration) {
+ Map<Object, Object> persistenceMap = ControllerModule.getPersistenceProperties(configuration);
+
+ if (!configuration.getPersistenceType().equals(PersistenceType.IN_MEMORY)) {
+ persistenceMap.put(JDBC_USER, configuration.getDatabaseUser());
+ persistenceMap.put(JDBC_PASSWORD, configuration.getDatabasePassword());
+ persistenceMap.put(PersistenceUnitProperties.CLASSLOADER, classLoader);
+ persistenceMap.put(PersistenceUnitProperties.WEAVING, "static");
+ }
+ return Persistence.createEntityManagerFactory(VIEWS_PERSISTENCE_UNIT_NAME, persistenceMap);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/SchemaManagerFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/SchemaManagerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/SchemaManagerFactory.java
new file mode 100644
index 0000000..ae730d1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/SchemaManagerFactory.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.persistence;
+
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.eclipse.persistence.tools.schemaframework.SchemaManager;
+
+/**
+ * Interface to get a SchemaManager
+ */
+public interface SchemaManagerFactory {
+ /**
+ * Get a SchemaManager for the given session.
+ *
+ * @param session the session
+ *
+ * @return the schema manager
+ */
+ public SchemaManager getSchemaManager(DatabaseSession session);
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 3e55558..bac1615 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -67,6 +67,7 @@ CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NO
CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));
CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name));
+CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -110,6 +111,7 @@ ALTER TABLE viewresource ADD CONSTRAINT FK_viewres_view_name FOREIGN KEY (view_n
ALTER TABLE viewinstance ADD CONSTRAINT FK_viewinst_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
ALTER TABLE viewinstanceproperty ADD CONSTRAINT FK_viewinstprop_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
ALTER TABLE viewinstancedata ADD CONSTRAINT FK_viewinstdata_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
+ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 1);
@@ -118,6 +120,7 @@ INSERT INTO ambari_sequences(sequence_name, value) values ('user_id_seq', 2);
INSERT INTO ambari_sequences(sequence_name, value) values ('configgroup_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('requestschedule_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('resourcefilter_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, value) values ('viewentity_id_seq', 0);
insert into roles(role_name)
select 'admin'
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 816d63c..2b7f4d5 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -57,6 +57,7 @@ CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NO
CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));
CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), "resource" VARCHAR(255), PRIMARY KEY(view_name, name));
+CREATE TABLE viewentity (id NUMBER(19) NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -100,6 +101,7 @@ ALTER TABLE viewresource ADD CONSTRAINT FK_viewres_view_name FOREIGN KEY (view_n
ALTER TABLE viewinstance ADD CONSTRAINT FK_viewinst_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
ALTER TABLE viewinstanceproperty ADD CONSTRAINT FK_viewinstprop_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
ALTER TABLE viewinstancedata ADD CONSTRAINT FK_viewinstdata_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
+ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
INSERT INTO ambari_sequences(sequence_name, value) values ('host_role_command_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('user_id_seq', 1);
@@ -107,6 +109,7 @@ INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 0);
INSERT INTO ambari_sequences(sequence_name, value) values ('configgroup_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('requestschedule_id_seq', 1);
INSERT INTO ambari_sequences(sequence_name, value) values ('resourcefilter_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, value) values ('viewentity_id_seq', 0);
INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariVersion}');
insert into Roles(role_name)
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index e3bcf68..0a7a432 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -92,6 +92,7 @@ CREATE TABLE ambari.viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(
CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
CREATE TABLE ambari.viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255), required CHAR(1), PRIMARY KEY(view_name, name));
CREATE TABLE ambari.viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name));
+CREATE TABLE ambari.viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id));
--------altering tables by creating foreign keys----------
ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -135,6 +136,7 @@ ALTER TABLE ambari.viewresource ADD CONSTRAINT FK_viewres_view_name FOREIGN KEY
ALTER TABLE ambari.viewinstance ADD CONSTRAINT FK_viewinst_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
ALTER TABLE ambari.viewinstanceproperty ADD CONSTRAINT FK_viewinstprop_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
ALTER TABLE ambari.viewinstancedata ADD CONSTRAINT FK_viewinstdata_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
+ALTER TABLE ambari.viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
---------inserting some data-----------
@@ -150,7 +152,9 @@ BEGIN;
union all
select 'requestschedule_id_seq', 1
union all
- select 'resourcefilter_id_seq', 1;
+ select 'resourcefilter_id_seq', 1
+ union all
+ select 'viewentity_id_seq', 0;
INSERT INTO ambari.Roles (role_name)
SELECT 'admin'
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index aa85db1..36cafe2 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -52,6 +52,7 @@
<class>org.apache.ambari.server.orm.entities.ViewInstancePropertyEntity</class>
<class>org.apache.ambari.server.orm.entities.ViewParameterEntity</class>
<class>org.apache.ambari.server.orm.entities.ViewResourceEntity</class>
+ <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>
<properties>
<!--<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/ambari" />-->
@@ -64,4 +65,14 @@
</properties>
</persistence-unit>
+ <!-- persistence unit for view persistence : entities are added dynamically -->
+ <persistence-unit name="ambari-views" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <exclude-unlisted-classes>false</exclude-unlisted-classes>
+ <properties>
+ <property name="eclipselink.cache.size.default" value="10000" />
+ <property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
+ <property name="eclipselink.weaving" value="static" />
+ </properties>
+ </persistence-unit>
</persistence>
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityEntityTest.java
new file mode 100644
index 0000000..023298b
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityEntityTest.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * ViewEntityEntity tests.
+ */
+public class ViewEntityEntityTest {
+ @Test
+ public void testSetGetId() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setId(99L);
+ Assert.assertEquals(99L, (long) viewEntityEntity.getId());
+ }
+
+ @Test
+ public void testSetGetViewName() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setViewName("foo");
+ Assert.assertEquals("foo", viewEntityEntity.getViewName());
+ }
+
+ @Test
+ public void testSetGetViewInstanceName() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setViewInstanceName("foo");
+ Assert.assertEquals("foo", viewEntityEntity.getViewInstanceName());
+ }
+
+ @Test
+ public void testSetGetClassName() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setClassName("TestClass");
+ Assert.assertEquals("TestClass", viewEntityEntity.getClassName());
+ }
+
+
+ @Test
+ public void testSetGetIdProperty() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setIdProperty("id");
+ Assert.assertEquals("id", viewEntityEntity.getIdProperty());
+ }
+
+ @Test
+ public void testSetGetViewInstance() throws Exception {
+ ViewInstanceEntity viewInstanceEntity = ViewInstanceEntityTest.getViewInstanceEntity();
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setViewInstance(viewInstanceEntity);
+ Assert.assertEquals(viewInstanceEntity, viewEntityEntity.getViewInstance());
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setId(99L);
+ viewEntityEntity.setClassName("TestClass");
+ viewEntityEntity.setIdProperty("id");
+ viewEntityEntity.setViewName("foo");
+ viewEntityEntity.setViewInstanceName("bar");
+
+ ViewEntityEntity viewEntityEntity2 = new ViewEntityEntity();
+ viewEntityEntity2.setId(99L);
+ viewEntityEntity2.setClassName("TestClass");
+ viewEntityEntity2.setIdProperty("id");
+ viewEntityEntity2.setViewName("foo");
+ viewEntityEntity2.setViewInstanceName("bar");
+
+ Assert.assertTrue(viewEntityEntity.equals(viewEntityEntity2));
+
+ viewEntityEntity2.setId(100L);
+
+ Assert.assertFalse(viewEntityEntity.equals(viewEntityEntity2));
+ }
+
+ @Test
+ public void testHashCode() throws Exception {
+ ViewEntityEntity viewEntityEntity = new ViewEntityEntity();
+ viewEntityEntity.setId(99L);
+ viewEntityEntity.setClassName("TestClass");
+ viewEntityEntity.setIdProperty("id");
+ viewEntityEntity.setViewName("foo");
+ viewEntityEntity.setViewInstanceName("bar");
+
+ ViewEntityEntity viewEntityEntity2 = new ViewEntityEntity();
+ viewEntityEntity2.setId(99L);
+ viewEntityEntity2.setClassName("TestClass");
+ viewEntityEntity2.setIdProperty("id");
+ viewEntityEntity2.setViewName("foo");
+ viewEntityEntity2.setViewInstanceName("bar");
+
+ Assert.assertEquals(viewEntityEntity.hashCode(), viewEntityEntity2.hashCode());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java
index 9bcf86a..b2dac99 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java
@@ -189,4 +189,14 @@ public class ViewEntityTest {
ViewEntity viewDefinition = getViewEntity();
Assert.assertEquals("view.jar", viewDefinition.getArchive());
}
+
+ @Test
+ public void testGetAmbariConfiguration() throws Exception {
+ ViewEntity viewDefinition = getViewEntity();
+ Configuration configuration = viewDefinition.getAmbariConfiguration();
+
+ Assert.assertEquals("v1", configuration.getProperty("p1"));
+ Assert.assertEquals("v2", configuration.getProperty("p2"));
+ Assert.assertEquals("v3", configuration.getProperty("p3"));
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog160Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog160Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog160Test.java
index a3de765..062338b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog160Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog160Test.java
@@ -34,6 +34,7 @@ import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertNull;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createNiceMock;
@@ -53,11 +54,13 @@ public class UpgradeCatalog160Test {
final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
Configuration configuration = createNiceMock(Configuration.class);
Capture<List<DBAccessor.DBColumnInfo>> hgConfigcolumnCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
+ Capture<List<DBAccessor.DBColumnInfo>> viewEntitycolumnCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
Capture<DBAccessor.DBColumnInfo> restartRequiredColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes();
setBPHostGroupConfigExpectations(dbAccessor, hgConfigcolumnCapture, restartRequiredColumnCapture);
+ setViewEntityConfigExpectations(dbAccessor, viewEntitycolumnCapture);
replay(dbAccessor, configuration);
AbstractUpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor);
@@ -70,15 +73,29 @@ public class UpgradeCatalog160Test {
verify(dbAccessor, configuration);
assertHGConfigColumns(hgConfigcolumnCapture);
+ assertViewEntityColumns(viewEntitycolumnCapture);
assertRestartRequiredColumn(restartRequiredColumnCapture);
}
@Test
public void testExecuteDMLUpdates() throws Exception {
+
+ Configuration configuration = createNiceMock(Configuration.class);
+ expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes();
+
final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
UpgradeCatalog160 upgradeCatalog = (UpgradeCatalog160) getUpgradeCatalog(dbAccessor);
+ replay(dbAccessor, configuration);
+
+ Class<?> c = AbstractUpgradeCatalog.class;
+ Field f = c.getDeclaredField("configuration");
+ f.setAccessible(true);
+ f.set(upgradeCatalog, configuration);
+
upgradeCatalog.executeDMLUpdates();
+
+ verify(dbAccessor, configuration);
}
@Test
@@ -116,6 +133,12 @@ public class UpgradeCatalog160Test {
"hostgroup_name", "hostgroup", "name", true);
}
+ private void setViewEntityConfigExpectations(DBAccessor dbAccessor,
+ Capture<List<DBAccessor.DBColumnInfo>> columnCapture) throws SQLException {
+
+ dbAccessor.createTable(eq("viewentity"), capture(columnCapture), eq("id"));
+ }
+
private void assertHGConfigColumns(Capture<List<DBAccessor.DBColumnInfo>> hgConfigcolumnCapture) {
List<DBAccessor.DBColumnInfo> columns = hgConfigcolumnCapture.getValue();
assertEquals(4, columns.size());
@@ -148,6 +171,54 @@ public class UpgradeCatalog160Test {
assertFalse(column.isNullable());
}
+ private void assertViewEntityColumns(Capture<List<DBAccessor.DBColumnInfo>> hgConfigcolumnCapture) {
+ List<DBAccessor.DBColumnInfo> columns = hgConfigcolumnCapture.getValue();
+ assertEquals(5, columns.size());
+
+
+ columns.add(new DBAccessor.DBColumnInfo("id", Long.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("view_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("view_instance_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("class_name", String.class, 255, null, false));
+ columns.add(new DBAccessor.DBColumnInfo("id_property", String.class, 255, null, true));
+
+
+ DBAccessor.DBColumnInfo column = columns.get(0);
+ assertEquals("id", column.getName());
+ assertNull(column.getLength());
+ assertEquals(Long.class, column.getType());
+ assertNull(column.getDefaultValue());
+ assertFalse(column.isNullable());
+
+ column = columns.get(1);
+ assertEquals("view_name", column.getName());
+ assertEquals(255, (int) column.getLength());
+ assertEquals(String.class, column.getType());
+ assertNull(column.getDefaultValue());
+ assertFalse(column.isNullable());
+
+ column = columns.get(2);
+ assertEquals("view_instance_name", column.getName());
+ assertEquals(255, (int) column.getLength());
+ assertEquals(String.class, column.getType());
+ assertNull(column.getDefaultValue());
+ assertFalse(column.isNullable());
+
+ column = columns.get(3);
+ assertEquals("class_name", column.getName());
+ assertEquals(255, (int) column.getLength());
+ assertEquals(String.class, column.getType());
+ assertNull(column.getDefaultValue());
+ assertFalse(column.isNullable());
+
+ column = columns.get(4);
+ assertEquals("id_property", column.getName());
+ assertEquals(255, (int) column.getLength());
+ assertEquals(String.class, column.getType());
+ assertNull(column.getDefaultValue());
+ assertTrue(column.isNullable());
+ }
+
private void assertRestartRequiredColumn(
Capture<DBAccessor.DBColumnInfo> restartRequiredColumnCapture) {
DBAccessor.DBColumnInfo column = restartRequiredColumnCapture.getValue();
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb57e05a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/EntityConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/EntityConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/EntityConfigTest.java
new file mode 100644
index 0000000..826a525
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/EntityConfigTest.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.view.configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBException;
+import java.util.List;
+
+/**
+ * EntityConfig tests.
+ */
+public class EntityConfigTest {
+
+ private final static String xml = "<view>\n" +
+ " <name>MY_VIEW</name>\n" +
+ " <label>My View!</label>\n" +
+ " <version>1.0.0</version>\n" +
+ " <instance>\n" +
+ " <name>INSTANCE1</name>\n" +
+ " </instance>\n" +
+ " <persistence>\n" +
+ " <entity>\n" +
+ " <class>org.apache.ambari.server.view.TestEntity1</class>\n" +
+ " <id-property>id</id-property>\n" +
+ " </entity>\n" +
+ " <entity>\n" +
+ " <class>org.apache.ambari.server.view.TestEntity2</class>\n" +
+ " <id-property>name</id-property>\n" +
+ " </entity>\n" +
+ " </persistence>" +
+ "</view>";
+
+
+ @Test
+ public void testGetClassName() throws Exception {
+ List<EntityConfig> entities = getEntityConfigs();
+
+ Assert.assertEquals(2, entities.size());
+
+ Assert.assertEquals("org.apache.ambari.server.view.TestEntity1", entities.get(0).getClassName());
+ Assert.assertEquals("org.apache.ambari.server.view.TestEntity2", entities.get(1).getClassName());
+ }
+
+ @Test
+ public void testGetIdProperty() throws Exception {
+ List<EntityConfig> entities = getEntityConfigs();
+
+ Assert.assertEquals(2, entities.size());
+
+ Assert.assertEquals("id", entities.get(0).getIdProperty());
+ Assert.assertEquals("name", entities.get(1).getIdProperty());
+ }
+
+ public static List<EntityConfig> getEntityConfigs() throws JAXBException {
+ ViewConfig config = ViewConfigTest.getConfig(xml);
+
+ PersistenceConfig persistenceConfig = config.getPersistence();
+
+ return persistenceConfig.getEntities();
+ }
+}