Procházet zdrojové kódy

AMBARI-5257 - Ambari Views : Persistence

tbeerbower před 11 roky
rodič
revize
7c198ac3c8
38 změnil soubory, kde provedl 2850 přidání a 498 odebrání
  1. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewExternalSubResourceService.java
  2. 2 8
      ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewInstanceService.java
  3. 7 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
  4. 176 17
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
  5. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewResourceProvider.java
  6. 106 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java
  7. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.java
  8. 267 91
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
  9. 107 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntity.java
  10. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntityPK.java
  11. 432 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
  12. 99 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityPK.java
  13. 168 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstancePropertyEntity.java
  14. 123 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstancePropertyEntityPK.java
  15. 157 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java
  16. 99 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntityPK.java
  17. 266 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewResourceEntity.java
  18. 99 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewResourceEntityPK.java
  19. 41 11
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
  20. 7 5
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewExternalSubResourceProvider.java
  21. 0 193
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceDefinition.java
  22. 2 1
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewProviderModule.java
  23. 247 68
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
  24. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewSubResourceDefinition.java
  25. 11 6
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewSubResourceProvider.java
  26. 27 0
      ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ResourceConfig.java
  27. 0 5
      ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
  28. 18 0
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  29. 11 0
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  30. 18 0
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  31. 6 0
      ambari-server/src/main/resources/META-INF/persistence.xml
  32. 3 3
      ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewExternalSubResourceServiceTest.java
  33. 27 25
      ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java
  34. 23 22
      ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
  35. 26 18
      ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java
  36. 18 13
      ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
  37. 3 1
      ambari-server/src/test/java/org/apache/ambari/server/view/ViewSubResourceDefinitionTest.java
  38. 31 0
      ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewExternalSubResourceService.java

@@ -20,7 +20,7 @@ package org.apache.ambari.server.api.services;
 
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.view.ViewInstanceDefinition;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -62,9 +62,9 @@ public class ViewExternalSubResourceService  extends BaseService {
 
   // ----- Constructors ------------------------------------------------------
 
-  public ViewExternalSubResourceService(Resource.Type type, ViewInstanceDefinition viewInstanceDefinition) {
+  public ViewExternalSubResourceService(Resource.Type type, ViewInstanceEntity viewInstanceDefinition) {
     this.type         = type;
-    this.viewName     = viewInstanceDefinition.getViewDefinition().getName();
+    this.viewName     = viewInstanceDefinition.getViewName();
     this.instanceName = viewInstanceDefinition.getName();
   }
 

+ 2 - 8
ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewInstanceService.java

@@ -20,7 +20,7 @@ package org.apache.ambari.server.api.services;
 
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.view.ViewInstanceDefinition;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.view.ViewRegistry;
 
 import javax.ws.rs.DELETE;
@@ -74,11 +74,6 @@ public class ViewInstanceService extends BaseService {
   public Response getService(@Context HttpHeaders headers, @Context UriInfo ui,
                              @PathParam("instanceName") String instanceName) {
 
-    if (ViewRegistry.getInstance().getInstanceDefinition(m_viewName, instanceName) == null) {
-      throw new IllegalArgumentException("A view instance " +
-          m_viewName + "/" + instanceName + " can not be found.");
-    }
-
     return handleRequest(headers, null, ui, Request.Type.GET,
         createServiceResource(m_viewName, instanceName));
   }
@@ -115,7 +110,6 @@ public class ViewInstanceService extends BaseService {
   @Produces("text/plain")
   public Response createService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                 @PathParam("instanceName") String instanceName) {
-
     return handleRequest(headers, body, ui, Request.Type.POST,
         createServiceResource(m_viewName, instanceName));
   }
@@ -205,7 +199,7 @@ public class ViewInstanceService extends BaseService {
   public Object getResourceHandler(@PathParam("instanceName") String instanceName,
                                             @PathParam("resources") String resources) {
 
-    ViewInstanceDefinition instanceDefinition =
+    ViewInstanceEntity instanceDefinition =
         ViewRegistry.getInstance().getInstanceDefinition(m_viewName, instanceName);
 
     if (instanceDefinition == null) {

+ 7 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java

@@ -50,7 +50,10 @@ import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.BlueprintDAO;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
+import org.apache.ambari.server.orm.dao.ViewDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.resources.ResourceManager;
 import org.apache.ambari.server.resources.api.rest.GetResource;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
@@ -66,7 +69,6 @@ import org.apache.ambari.server.security.unsecured.rest.CertificateSign;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.ambari.server.utils.VersionUtils;
-import org.apache.ambari.server.view.ViewInstanceDefinition;
 import org.apache.ambari.server.view.ViewRegistry;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Server;
@@ -285,8 +287,9 @@ public class AmbariServer {
 
       HandlerList handlerList = new HandlerList();
 
-      for (ViewInstanceDefinition viewInstanceDefinition : ViewRegistry.readViewArchives(configs)){
-        handlerList.addHandler(ViewRegistry.getWebAppContext(viewInstanceDefinition));
+      ViewRegistry viewRegistry = ViewRegistry.getInstance();
+      for (ViewInstanceEntity entity : viewRegistry.readViewArchives(configs)){
+        handlerList.addHandler(viewRegistry.getWebAppContext(entity));
       }
       handlerList.addHandler(root);
 
@@ -507,6 +510,7 @@ public class AmbariServer {
     AbstractControllerResourceProvider.init(injector.getInstance(ResourceProviderFactory.class));
     BlueprintResourceProvider.init(injector.getInstance(BlueprintDAO.class), injector.getInstance(Gson.class));
     ClusterResourceProvider.injectBlueprintDAO(injector.getInstance(BlueprintDAO.class));
+    ViewRegistry.init(injector.getInstance(ViewDAO.class), injector.getInstance(ViewInstanceDAO.class));
   }
 
   public static void main(String[] args) throws Exception {

+ 176 - 17
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java

@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.controller.internal;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -27,13 +28,18 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
-import org.apache.ambari.server.view.ViewDefinition;
-import org.apache.ambari.server.view.ViewInstanceDefinition;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstancePropertyEntity;
 import org.apache.ambari.server.view.ViewRegistry;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
@@ -48,8 +54,15 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
   public static final String VIEW_NAME_PROPERTY_ID     = "ViewInstanceInfo/view_name";
   public static final String INSTANCE_NAME_PROPERTY_ID = "ViewInstanceInfo/instance_name";
   public static final String PROPERTIES_PROPERTY_ID    = "ViewInstanceInfo/properties";
+  public static final String DATA_PROPERTY_ID          = "ViewInstanceInfo/instance_data";
   public static final String CONTEXT_PATH_PROPERTY_ID  = "ViewInstanceInfo/context_path";
 
+  /**
+   * Property prefix values.
+   */
+  private static final String PROPERTIES_PREFIX = PROPERTIES_PROPERTY_ID + "/";
+  private static final String DATA_PREFIX       = DATA_PROPERTY_ID + "/";
+
   /**
    * The key property ids for a view instance resource.
    */
@@ -67,10 +80,10 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
     propertyIds.add(VIEW_NAME_PROPERTY_ID);
     propertyIds.add(INSTANCE_NAME_PROPERTY_ID);
     propertyIds.add(PROPERTIES_PROPERTY_ID);
+    propertyIds.add(DATA_PROPERTY_ID);
     propertyIds.add(CONTEXT_PATH_PROPERTY_ID);
   }
 
-
   // ----- Constructors ------------------------------------------------------
 
   /**
@@ -87,7 +100,12 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
   public RequestStatus createResources(Request request)
       throws SystemException, UnsupportedPropertyException,
              ResourceAlreadyExistsException, NoSuchParentResourceException {
-    throw new UnsupportedOperationException("Not yet supported.");
+    for (Map<String, Object> properties : request.getProperties()) {
+      createResources(getCreateCommand(properties));
+    }
+    notifyCreate(Resource.Type.ViewInstance, request);
+
+    return getRequestStatus(null);
   }
 
   @Override
@@ -108,19 +126,11 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
       String viewName = (String) propertyMap.get(VIEW_NAME_PROPERTY_ID);
       String instanceName = (String) propertyMap.get(INSTANCE_NAME_PROPERTY_ID);
 
-      for (ViewDefinition viewDefinition : viewRegistry.getDefinitions()){
+      for (ViewEntity viewDefinition : viewRegistry.getDefinitions()){
         if (viewName == null || viewName.equals(viewDefinition.getName())) {
-          for (ViewInstanceDefinition viewInstanceDefinition : viewRegistry.getInstanceDefinitions(viewDefinition)) {
+          for (ViewInstanceEntity viewInstanceDefinition : viewRegistry.getInstanceDefinitions(viewDefinition)) {
             if (instanceName == null || instanceName.equals(viewInstanceDefinition.getName())) {
-              Resource resource = new ResourceImpl(Resource.Type.ViewInstance);
-
-              setResourceProperty(resource, VIEW_NAME_PROPERTY_ID, viewDefinition.getName(), requestedIds);
-              setResourceProperty(resource, INSTANCE_NAME_PROPERTY_ID, viewInstanceDefinition.getName(), requestedIds);
-              setResourceProperty(resource, PROPERTIES_PROPERTY_ID,
-                  viewInstanceDefinition.getProperties(), requestedIds);
-              setResourceProperty(resource, CONTEXT_PATH_PROPERTY_ID,
-                  viewInstanceDefinition.getContextPath(), requestedIds);
-
+              Resource resource = toResource(viewInstanceDefinition, requestedIds);
               resources.add(resource);
             }
           }
@@ -133,13 +143,25 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
   @Override
   public RequestStatus updateResources(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
-    throw new UnsupportedOperationException("Not yet supported.");
+
+    Iterator<Map<String,Object>> iterator = request.getProperties().iterator();
+    if (iterator.hasNext()) {
+      for (Map<String, Object> propertyMap : getPropertyMaps(iterator.next(), predicate)) {
+        modifyResources(getUpdateCommand(propertyMap));
+      }
+    }
+    notifyUpdate(Resource.Type.ViewInstance, request, predicate);
+
+    return getRequestStatus(null);
   }
 
   @Override
   public RequestStatus deleteResources(Predicate predicate)
       throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
-    throw new UnsupportedOperationException("Not yet supported.");
+
+    modifyResources(getDeleteCommand(predicate));
+    notifyDelete(Resource.Type.ViewInstance, predicate);
+    return getRequestStatus(null);
   }
 
   @Override
@@ -154,4 +176,141 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
   protected Set<String> getPKPropertyIds() {
     return new HashSet<String>(keyPropertyIds.values());
   }
+
+
+  // ----- helper methods ----------------------------------------------------
+
+  // Convert an instance entity to a resource
+  private Resource toResource(ViewInstanceEntity viewInstanceEntity, Set<String> requestedIds) {
+    Resource resource = new ResourceImpl(Resource.Type.ViewInstance);
+
+    String viewName = viewInstanceEntity.getViewName();
+    String name     = viewInstanceEntity.getName();
+
+    setResourceProperty(resource, VIEW_NAME_PROPERTY_ID, viewName, requestedIds);
+    setResourceProperty(resource, INSTANCE_NAME_PROPERTY_ID, name, requestedIds);
+    Map<String, String> properties = new HashMap<String, String>();
+
+    for (ViewInstancePropertyEntity viewInstancePropertyEntity : viewInstanceEntity.getProperties()) {
+      properties.put(viewInstancePropertyEntity.getName(), viewInstancePropertyEntity.getValue());
+    }
+    setResourceProperty(resource, PROPERTIES_PROPERTY_ID,
+        properties, requestedIds);
+    Map<String, String> applicationData = new HashMap<String, String>();
+
+    for (ViewInstanceDataEntity viewInstanceDataEntity : viewInstanceEntity.getData()) {
+      applicationData.put(viewInstanceDataEntity.getName(), viewInstanceDataEntity.getValue());
+    }
+    setResourceProperty(resource, DATA_PROPERTY_ID,
+        applicationData, requestedIds);
+    setResourceProperty(resource, CONTEXT_PATH_PROPERTY_ID,
+        ViewInstanceEntity.getContextPath(viewName, name), requestedIds);
+
+    return resource;
+  }
+
+  // Convert a map of properties to a view instance entity.
+  private ViewInstanceEntity toEntity(Map<String, Object> properties) {
+    String name     = (String) properties.get(INSTANCE_NAME_PROPERTY_ID);
+    if (name == null || name.isEmpty()) {
+      throw new IllegalArgumentException("View instance name must be provided");
+    }
+
+    String viewName = (String) properties.get(VIEW_NAME_PROPERTY_ID);
+    if (viewName == null || viewName.isEmpty()) {
+      throw new IllegalArgumentException("View name must be provided");
+    }
+
+    ViewInstanceEntity viewInstanceEntity = new ViewInstanceEntity();
+    viewInstanceEntity.setName(name);
+    viewInstanceEntity.setViewName(viewName);
+
+
+    ViewEntity viewEntity = new ViewEntity();
+    viewEntity.setName(viewName);
+
+    viewInstanceEntity.setViewEntity(viewEntity);
+
+    Collection<ViewInstancePropertyEntity> instanceProperties = new HashSet<ViewInstancePropertyEntity>();
+    Collection<ViewInstanceDataEntity>     instanceData       = new HashSet<ViewInstanceDataEntity>();
+
+    for (Map.Entry<String, Object> entry : properties.entrySet()) {
+
+      String propertyName = entry.getKey();
+
+      if (propertyName.startsWith(PROPERTIES_PREFIX)) {
+        ViewInstancePropertyEntity viewInstancePropertyEntity = new ViewInstancePropertyEntity();
+
+        viewInstancePropertyEntity.setViewName(viewName);
+        viewInstancePropertyEntity.setViewInstanceName(name);
+        viewInstancePropertyEntity.setName(entry.getKey().substring(PROPERTIES_PREFIX.length()));
+        viewInstancePropertyEntity.setValue((String) entry.getValue());
+        viewInstancePropertyEntity.setViewInstanceEntity(viewInstanceEntity);
+
+        instanceProperties.add(viewInstancePropertyEntity);
+      } else if (propertyName.startsWith(DATA_PREFIX)) {
+        ViewInstanceDataEntity viewInstanceDataEntity = new ViewInstanceDataEntity();
+
+        viewInstanceDataEntity.setViewName(viewName);
+        viewInstanceDataEntity.setViewInstanceName(name);
+        viewInstanceDataEntity.setName(entry.getKey().substring(DATA_PREFIX.length()));
+        viewInstanceDataEntity.setValue((String) entry.getValue());
+        viewInstanceDataEntity.setViewInstanceEntity(viewInstanceEntity);
+
+        instanceData.add(viewInstanceDataEntity);
+      }
+    }
+    viewInstanceEntity.setProperties(instanceProperties);
+    viewInstanceEntity.setData(instanceData);
+
+    return viewInstanceEntity;
+  }
+
+  // Create a create command with all properties set.
+  private Command<Void> getCreateCommand(final Map<String, Object> properties) {
+    return new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        ViewRegistry.getInstance().installViewInstance(toEntity(properties));
+        return null;
+      }
+    };
+  }
+
+  // Create an update command with all properties set.
+  private Command<Void> getUpdateCommand(final Map<String, Object> properties) {
+    return new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        ViewRegistry.getInstance().updateViewInstance(toEntity(properties));
+        return null;
+      }
+    };
+  }
+
+  // Create a delete command with the given predicate.
+  private Command<Void> getDeleteCommand(final Predicate predicate) {
+    return new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        Set<String>  requestedIds = getRequestPropertyIds(PropertyHelper.getReadRequest(), predicate);
+        ViewRegistry viewRegistry = ViewRegistry.getInstance();
+
+        Set<ViewInstanceEntity> viewInstanceEntities = new HashSet<ViewInstanceEntity>();
+
+        for (ViewEntity viewEntity : viewRegistry.getDefinitions()){
+          for (ViewInstanceEntity viewInstanceEntity : viewRegistry.getInstanceDefinitions(viewEntity)){
+            Resource resource = toResource(viewInstanceEntity, requestedIds);
+            if (predicate == null || predicate.evaluate(resource)) {
+              viewInstanceEntities.add(viewInstanceEntity);
+            }
+          }
+        }
+        for (ViewInstanceEntity viewInstanceEntity : viewInstanceEntities) {
+          viewRegistry.uninstallViewInstance(viewInstanceEntity);
+        }
+        return null;
+      }
+    };
+  }
 }

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewResourceProvider.java

@@ -27,7 +27,7 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
-import org.apache.ambari.server.view.ViewDefinition;
+import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.view.ViewRegistry;
 
 import java.util.Collections;
@@ -108,7 +108,7 @@ public class ViewResourceProvider extends AbstractResourceProvider {
 
       String viewName = (String) propertyMap.get(VIEW_NAME_PROPERTY_ID);
 
-      for (ViewDefinition viewDefinition : viewRegistry.getDefinitions()){
+      for (ViewEntity viewDefinition : viewRegistry.getDefinitions()){
         if (viewName == null || viewName.equals(viewDefinition.getName())) {
           Resource resource = new ResourceImpl(Resource.Type.View);
 
@@ -117,7 +117,7 @@ public class ViewResourceProvider extends AbstractResourceProvider {
           setResourceProperty(resource, VERSION_PROPERTY_ID, viewDefinition.getVersion(), requestedIds);
           setResourceProperty(resource, PARAMETERS_PROPERTY_ID,
               viewDefinition.getConfiguration().getParameters(), requestedIds);
-          setResourceProperty(resource, ARCHIVE_PROPERTY_ID, viewDefinition.getArchivePath(), requestedIds);
+          setResourceProperty(resource, ARCHIVE_PROPERTY_ID, viewDefinition.getArchive(), requestedIds);
 
           resources.add(resource);
         }

+ 106 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewDAO.java

@@ -0,0 +1,106 @@
+/**
+ * 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.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+/**
+ * View Data Access Object.
+ */
+@Singleton
+public class ViewDAO {
+  /**
+   * JPA entity manager
+   */
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * Find a view with a given name.
+   *
+   * @param viewName name of view to find
+   *
+   * @return  a matching view or null
+   */
+  public ViewEntity findByName(String viewName) {
+    return entityManagerProvider.get().find(ViewEntity.class, viewName);
+  }
+
+  /**
+   * Find all views.
+   *
+   * @return all views or an empty List
+   */
+  public List<ViewEntity> findAll() {
+    TypedQuery<ViewEntity> query = entityManagerProvider.get().
+        createNamedQuery("allViews", ViewEntity.class);
+
+    return query.getResultList();
+  }
+
+  /**
+   * Refresh the state of the instance from the database,
+   * overwriting changes made to the entity, if any.
+   *
+   * @param ViewEntity  entity to refresh
+   */
+  @Transactional
+  public void refresh(ViewEntity ViewEntity) {
+    entityManagerProvider.get().refresh(ViewEntity);
+  }
+
+  /**
+   * Make an instance managed and persistent.
+   *
+   * @param ViewEntity  entity to persist
+   */
+  @Transactional
+  public void create(ViewEntity ViewEntity) {
+    entityManagerProvider.get().persist(ViewEntity);
+  }
+
+  /**
+   * Merge the state of the given entity into the current persistence context.
+   *
+   * @param ViewEntity  entity to merge
+   * @return the merged entity
+   */
+  @Transactional
+  public ViewEntity merge(ViewEntity ViewEntity) {
+    return entityManagerProvider.get().merge(ViewEntity);
+  }
+
+  /**
+   * Remove the entity instance.
+   *
+   * @param ViewEntity  entity to remove
+   */
+  @Transactional
+  public void remove(ViewEntity ViewEntity) {
+    entityManagerProvider.get().remove(merge(ViewEntity));
+  }
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.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.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntityPK;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+/**
+ * View Instance Data Access Object.
+ */
+@Singleton
+public class ViewInstanceDAO {
+  /**
+   * JPA entity manager
+   */
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * Find a view with the given names.
+   *
+   * @param viewName      name of view
+   * @param instanceName  name of the instance
+   *
+   * @return  a matching view instance or null
+   */
+  public ViewInstanceEntity findByName(String viewName, String instanceName) {
+    EntityManager entityManager = entityManagerProvider.get();
+    ViewInstanceEntityPK pk = new ViewInstanceEntityPK();
+    pk.setViewName(viewName);
+    pk.setName(instanceName);
+
+    return entityManager.find(ViewInstanceEntity.class, pk);
+  }
+
+  /**
+   * Find all view instances.
+   *
+   * @return all views or an empty List
+   */
+  public List<ViewInstanceEntity> findAll() {
+    TypedQuery<ViewInstanceEntity> query = entityManagerProvider.get().
+        createNamedQuery("allViewInstances", ViewInstanceEntity.class);
+
+    return query.getResultList();
+  }
+
+  /**
+   * Refresh the state of the instance from the database,
+   * overwriting changes made to the entity, if any.
+   *
+   * @param ViewInstanceEntity  entity to refresh
+   */
+  @Transactional
+  public void refresh(ViewInstanceEntity ViewInstanceEntity) {
+    entityManagerProvider.get().refresh(ViewInstanceEntity);
+  }
+
+  /**
+   * Make an instance managed and persistent.
+   *
+   * @param ViewInstanceEntity  entity to persist
+   */
+  @Transactional
+  public void create(ViewInstanceEntity ViewInstanceEntity) {
+    entityManagerProvider.get().persist(ViewInstanceEntity);
+  }
+
+  /**
+   * Merge the state of the given entity into the current persistence context.
+   *
+   * @param ViewInstanceEntity  entity to merge
+   * @return the merged entity
+   */
+  @Transactional
+  public ViewInstanceEntity merge(ViewInstanceEntity ViewInstanceEntity) {
+    return entityManagerProvider.get().merge(ViewInstanceEntity);
+  }
+
+  /**
+   * Remove the entity instance.
+   *
+   * @param ViewInstanceEntity  entity to remove
+   */
+  @Transactional
+  public void remove(ViewInstanceEntity ViewInstanceEntity) {
+    entityManagerProvider.get().remove(merge(ViewInstanceEntity));
+  }
+}

+ 267 - 91
ambari-server/src/main/java/org/apache/ambari/server/view/ViewDefinition.java → ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java

@@ -16,92 +16,169 @@
  * limitations under the License.
  */
 
-package org.apache.ambari.server.view;
+package org.apache.ambari.server.orm.entities;
 
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.view.configuration.ResourceConfig;
-import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.view.ViewSubResourceDefinition;
+import org.apache.ambari.server.view.configuration.ResourceConfig;
+import org.apache.ambari.server.view.configuration.ViewConfig;
 
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
 /**
- * Provides access to the attributes of a view.
+ * Entity representing a View.
  */
-public class ViewDefinition {
+@Table(name = "viewmain")
+@NamedQuery(name = "allViews",
+    query = "SELECT view FROM ViewEntity view")
+@Entity
+public class ViewEntity {
   /**
-   * The associated view configuration.
+   * The unique view name.
    */
-  private final ViewConfig configuration;
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true,
+      updatable = false, unique = true, length = 100)
+  private String name;
 
   /**
-   * The mapping of resource type to resource provider.
+   * The public view name.
    */
-  private final Map<Resource.Type, ResourceProvider> resourceProviders = new HashMap<Resource.Type, ResourceProvider>();
+  @Column
+  @Basic
+  private String label;
 
   /**
-   * The mapping of resource type to resource definition.
+   * The view version.
    */
-  private final Map<Resource.Type, ViewSubResourceDefinition> resourceDefinitions = new HashMap<Resource.Type, ViewSubResourceDefinition>();
+  @Column
+  @Basic
+  private String version;
 
   /**
-   * The mapping of resource type to resource configuration.
+   * The view archive.
    */
-  private final Map<Resource.Type, ResourceConfig> resourceConfigurations = new HashMap<Resource.Type, ResourceConfig>();
+  @Column
+  @Basic
+  private String archive;
 
   /**
-   * The mapping of instance name to instance definition.
+   * The list of view parameters.
    */
-  private final Map<String, ViewInstanceDefinition> instanceDefinitions = new HashMap<String, ViewInstanceDefinition>();
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
+  private Collection<ViewParameterEntity> parameters = new HashSet<ViewParameterEntity>();
+
+  /**
+   * The list of view resources.
+   */
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
+  private Collection<ViewResourceEntity> resources = new HashSet<ViewResourceEntity>();
+
+  /**
+   * The list of view instances.
+   */
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
+  private Collection<ViewInstanceEntity> instances = new HashSet<ViewInstanceEntity>();
+
+
+  // ----- Transient data ----------------------------------------------------
+
+  /**
+   * The associated view configuration.
+   */
+  @Transient
+  private final ViewConfig configuration;
 
   /**
    * The Ambari configuration properties.
    */
+  @Transient
   private final Configuration ambariConfiguration;
 
   /**
    * The external resource type for the view.
    */
+  @Transient
   private final Resource.Type externalResourceType;
 
   /**
    * The classloader used to load the view.
    */
+  @Transient
   private final ClassLoader classLoader;
 
   /**
-   * The archive path for the view.
+   * The mapping of resource type to resource provider.
    */
-  private final String archivePath;
+  @Transient
+  private final Map<Resource.Type, ResourceProvider> resourceProviders = new HashMap<Resource.Type, ResourceProvider>();
+
+  /**
+   * The mapping of resource type to resource definition.
+   */
+  @Transient
+  private final Map<Resource.Type, ViewSubResourceDefinition> resourceDefinitions = new HashMap<Resource.Type, ViewSubResourceDefinition>();
+
+  /**
+   * The mapping of resource type to resource configuration.
+   */
+  @Transient
+  private final Map<Resource.Type, ResourceConfig> resourceConfigurations = new HashMap<Resource.Type, ResourceConfig>();
 
 
   // ----- Constructors ------------------------------------------------------
 
   /**
-   * Construct a view definition from the given configuration.
+   * Construct a view entity.
+   */
+  public ViewEntity() {
+    this.configuration        = null;
+    this.ambariConfiguration  = null;
+    this.classLoader          = null;
+    this.archive              = null;
+    this.externalResourceType = null;
+  }
+
+  /**
+   * Construct a view entity from the given configuration.
    *
    * @param configuration        the view configuration
    * @param ambariConfiguration  the Ambari configuration
    * @param classLoader          the class loader
    * @param archivePath          the path of the view archive
    */
-  public ViewDefinition(ViewConfig configuration, Configuration ambariConfiguration,
+  public ViewEntity(ViewConfig configuration, Configuration ambariConfiguration,
                         ClassLoader classLoader, String archivePath) {
     this.configuration       = configuration;
     this.ambariConfiguration = ambariConfiguration;
     this.classLoader         = classLoader;
-    this.archivePath         = archivePath;
+    this.archive             = archivePath;
+
+    this.name    = configuration.getName();
+    this.label   = configuration.getLabel();
+    this.version = configuration.getVersion();
 
     this.externalResourceType =
         new Resource.Type(getQualifiedResourceTypeName(ResourceConfig.EXTERNAL_RESOURCE_PLURAL_NAME));
   }
 
 
-  // ----- ViewDefinition ----------------------------------------------------
+  // ----- ViewEntity --------------------------------------------------------
 
   /**
    * Get the view name.
@@ -109,16 +186,34 @@ public class ViewDefinition {
    * @return the view name
    */
   public String getName() {
-    return configuration.getName();
+    return name;
+  }
+
+  /**
+   * Set the view name.
+   *
+   * @param name the view name
+   */
+  public void setName(String name) {
+    this.name = name;
   }
 
   /**
-   * Get the view label.
+   * Get the view label (display name).
    *
    * @return the view label
    */
   public String getLabel() {
-    return configuration.getLabel();
+    return label;
+  }
+
+  /**
+   * Set the view label (display name).
+   *
+   * @param label  the view label
+   */
+  public void setLabel(String label) {
+    this.label = label;
   }
 
   /**
@@ -127,16 +222,126 @@ public class ViewDefinition {
    * @return the version
    */
   public String getVersion() {
-    return configuration.getVersion();
+    return version;
   }
 
   /**
-   * Get the associated view configuration.
+   * Set the view version.
    *
-   * @return the configuration
+   * @param version  the version
    */
-  public ViewConfig getConfiguration() {
-    return configuration;
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  /**
+   * Get the view parameters.
+   *
+   * @return the view parameters
+   */
+  public Collection<ViewParameterEntity> getParameters() {
+    return parameters;
+  }
+
+  /**
+   * Set the view parameters.
+   *
+   * @param parameters  the view parameters
+   */
+  public void setParameters(Collection<ViewParameterEntity> parameters) {
+    this.parameters = parameters;
+  }
+
+  /**
+   * Get the view resources.
+   *
+   * @return the view resources
+   */
+  public Collection<ViewResourceEntity> getResources() {
+    return resources;
+  }
+
+  /**
+   * Set the view resources.
+   *
+   * @param resources  the view resources
+   */
+  public void setResources(Collection<ViewResourceEntity> resources) {
+    this.resources = resources;
+  }
+
+  /**
+   * Get the view instances.
+   *
+   * @return the view instances
+   */
+  public Collection<ViewInstanceEntity> getInstances() {
+    return instances;
+  }
+
+  /**
+   * Set the view instances.
+   *
+   * @param instances  the instances
+   */
+  public void setInstances(Collection<ViewInstanceEntity> instances) {
+    this.instances = instances;
+  }
+
+  /**
+   * Add an instance definition.
+   *
+   * @param viewInstanceDefinition  the instance definition
+   */
+  public void addInstanceDefinition(ViewInstanceEntity viewInstanceDefinition) {
+    removeInstanceDefinition(viewInstanceDefinition.getName());
+    instances.add(viewInstanceDefinition);
+  }
+
+  /**
+   * Remove an instance definition.
+   *
+   * @param instanceName  the instance name
+   */
+  public void removeInstanceDefinition(String instanceName) {
+    ViewInstanceEntity entity = getInstanceDefinition(instanceName);
+    if (entity != null) {
+      instances.remove(entity);
+    }
+  }
+
+  /**
+   * Get an instance definition for the given name.
+   *
+   * @param instanceName  the instance name
+   *
+   * @return the instance definition
+   */
+  public ViewInstanceEntity getInstanceDefinition(String instanceName) {
+    for (ViewInstanceEntity viewInstanceEntity : instances) {
+      if (viewInstanceEntity.getName().equals(instanceName)) {
+        return viewInstanceEntity;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Get the path of the view archive.
+   *
+   * @return  the path of the view archive
+   */
+  public String getArchive() {
+    return archive;
+  }
+
+  /**
+   * Set the view archive path.
+   *
+   * @param archive  the view archive path
+   */
+  public void setArchive(String archive) {
+    this.archive = archive;
   }
 
   /**
@@ -150,6 +355,35 @@ public class ViewDefinition {
     return ambariConfiguration.getProperty(key);
   }
 
+  /**
+   * Get a resource name qualified by the associated view name.
+   *
+   * @param resourceTypeName  the resource type name
+   *
+   * @return the qualified resource name
+   */
+  public String getQualifiedResourceTypeName(String resourceTypeName) {
+    return getName() + "/" + resourceTypeName;
+  }
+
+  /**
+   * Get the external resource type for the view.
+   *
+   * @return the external resource type
+   */
+  public Resource.Type getExternalResourceType() {
+    return externalResourceType;
+  }
+
+  /**
+   * Get the class loader used to load the view classes.
+   *
+   * @return the class loader
+   */
+  public ClassLoader getClassLoader() {
+    return classLoader;
+  }
+
   /**
    * Add a resource provider for the given type.
    *
@@ -229,69 +463,11 @@ public class ViewDefinition {
   }
 
   /**
-   * Add an instance definition.
-   *
-   * @param viewInstanceDefinition  the instance definition
-   */
-  public void addInstanceDefinition(ViewInstanceDefinition viewInstanceDefinition) {
-    instanceDefinitions.put(viewInstanceDefinition.getName(), viewInstanceDefinition);
-  }
-
-  /**
-   * Get the collection of all instance definitions for this view.
-   *
-   * @return the collection of instance definitions
-   */
-  public Collection<ViewInstanceDefinition> getInstanceDefinitions() {
-    return instanceDefinitions.values();
-  }
-
-  /**
-   * Get an instance definition for the given name.
-   *
-   * @param instanceName  the instance name
-   *
-   * @return the instance definition
-   */
-  public ViewInstanceDefinition getInstanceDefinition(String instanceName) {
-    return instanceDefinitions.get(instanceName);
-  }
-
-  /**
-   * Get the external resource type for the view.
-   *
-   * @return the external resource type
-   */
-  public Resource.Type getExternalResourceType() {
-    return externalResourceType;
-  }
-
-  /**
-   * Get a resource name qualified by the associated view name.
-   *
-   * @param resourceTypeName  the resource type name
-   *
-   * @return the qualified resource name
-   */
-  public String getQualifiedResourceTypeName(String resourceTypeName) {
-    return configuration.getName() + "/" + resourceTypeName;
-  }
-
-  /**
-   * Get the class loader used to load the view classes.
-   *
-   * @return the class loader
-   */
-  public ClassLoader getClassLoader() {
-    return classLoader;
-  }
-
-  /**
-   * Get the path for the archive for the view.
+   * Get the associated view configuration.
    *
-   * @return the archive path
+   * @return the configuration
    */
-  public String getArchivePath() {
-    return archivePath;
+  public ViewConfig getConfiguration() {
+    return configuration;
   }
 }

+ 107 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntity.java

@@ -0,0 +1,107 @@
+/**
+ * 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.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Represents a property of a View instance.
+ */
+@javax.persistence.IdClass(ViewInstanceDataEntityPK.class)
+@Table(name = "viewinstancedata")
+@Entity
+public class ViewInstanceDataEntity {
+
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+  private String viewName;
+
+  @Id
+  @Column(name = "view_instance_name", nullable = false, insertable = false, updatable = false)
+  private String viewInstanceName;
+
+  /**
+   * The data key.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false)
+  private String name;
+
+  /**
+   * The property value.
+   */
+  @Column
+  @Basic
+  private String value;
+
+  @ManyToOne
+  @JoinColumns({
+      @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false),
+      @JoinColumn(name = "view_instance_name", referencedColumnName = "name", nullable = false)
+  })
+  private ViewInstanceEntity viewInstance;
+
+
+  public String getViewName() {
+    return viewName;
+  }
+
+  public void setViewName(String viewName) {
+    this.viewName = viewName;
+  }
+
+  public String getViewInstanceName() {
+    return viewInstanceName;
+  }
+
+  public void setViewInstanceName(String viewInstanceName) {
+    this.viewInstanceName = viewInstanceName;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  public ViewInstanceEntity getViewInstanceEntity() {
+    return viewInstance;
+  }
+
+  public void setViewInstanceEntity(ViewInstanceEntity viewInstance) {
+    this.viewInstance = viewInstance;
+  }
+}

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceDataEntityPK.java

@@ -0,0 +1,101 @@
+/**
+ * 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.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for ViewInstanceDataEntity.
+ */
+public class ViewInstanceDataEntityPK {
+
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewName;
+
+  @Id
+  @Column(name = "view_instance_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewInstanceName;
+
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String name;
+
+  /**
+   * Get the name of the associated view.
+   *
+   * @return view name
+   */
+  public String getViewName() {
+    return viewName;
+  }
+
+  /**
+   * Set the name of the associated view.
+   *
+   * @param viewName  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 name of the host group.
+   *
+   * @return host group name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of the host group.
+   *
+   * @param name  host group name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewInstanceDataEntityPK that = (ViewInstanceDataEntityPK) o;
+
+    return this.viewName.equals(that.viewName) &&
+        this.viewInstanceName.equals(that.viewInstanceName) &&
+        this.name.equals(that.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * viewName.hashCode() + viewInstanceName.hashCode() + name.hashCode();
+  }
+}

+ 432 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java

@@ -0,0 +1,432 @@
+/**
+ * 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.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.view.configuration.InstanceConfig;
+import org.apache.ambari.view.ResourceProvider;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * Represents an instance of a View.
+ */
+@javax.persistence.IdClass(ViewInstanceEntityPK.class)
+@Table(name = "viewinstance")
+@NamedQuery(name = "allViewInstances",
+    query = "SELECT viewInstance FROM ViewInstanceEntity viewInstance")
+@Entity
+public class ViewInstanceEntity {
+  /**
+   * The prefix for every view instance context path.
+   */
+  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
+
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+  private String viewName;
+
+  /**
+   * The instance name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false)
+  private String name;
+
+  /**
+   * The instance properties.
+   */
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "viewInstance")
+  private Collection<ViewInstancePropertyEntity> properties = new HashSet<ViewInstancePropertyEntity>();
+
+  /**
+   * The instance data.
+   */
+  @OneToMany(cascade = CascadeType.ALL, mappedBy = "viewInstance")
+  private Collection<ViewInstanceDataEntity> data = new HashSet<ViewInstanceDataEntity>();
+
+  @ManyToOne
+  @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false)
+  private ViewEntity view;
+
+
+  // ----- transient data ----------------------------------------------------
+
+  /**
+   * The associated configuration.  This will be null if the instance was not
+   * defined in the archive.
+   */
+  @Transient
+  private final InstanceConfig instanceConfig;
+
+  /**
+   * The mapping of resource type to resource provider.  Calculated when the
+   * instance is added.
+   */
+  @Transient
+  private final Map<Resource.Type, ResourceProvider> resourceProviders = new HashMap<Resource.Type, ResourceProvider>();
+
+  /**
+   * The mapping of the resource plural name to service.  Calculated when the
+   * instance is added.
+   */
+  @Transient
+  private final Map<String, Object> services = new HashMap<String, Object>();
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  public ViewInstanceEntity() {
+    instanceConfig = null;
+  }
+
+  /**
+   * Construct a view instance definition.
+   *
+   * @param view  the parent view definition
+   * @param instanceConfig  the associated configuration
+   */
+  public ViewInstanceEntity(ViewEntity view, InstanceConfig instanceConfig) {
+    this.name           = instanceConfig.getName();
+    this.instanceConfig = instanceConfig;
+    this.view           = view;
+    this.viewName       = view.getName();
+  }
+
+  /**
+   * Construct a view instance definition.
+   *
+   * @param view  the parent view definition
+   * @param name  the instance name
+   */
+  public ViewInstanceEntity(ViewEntity view, String name) {
+    this.name           = name;
+    this.instanceConfig = null;
+    this.view           = view;
+    this.viewName       = view.getName();
+  }
+
+
+  // ----- ViewInstanceEntity ------------------------------------------------
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Get the name of this instance.
+   *
+   * @return the instance name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of this instance.
+   *
+   * @param name  the instance name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Get the instance properties.
+   *
+   * @return the instance properties
+   */
+  public Collection<ViewInstancePropertyEntity> getProperties() {
+    return properties;
+  }
+
+  /**
+   * Get the instance property map.
+   *
+   * @return the map of instance properties
+   */
+  public Map<String, String> getPropertyMap() {
+    Map<String, String> propertyMap = new HashMap<String, String>();
+
+    for (ViewInstancePropertyEntity viewInstancePropertyEntity : properties) {
+      propertyMap.put(viewInstancePropertyEntity.getName(), viewInstancePropertyEntity.getValue());
+    }
+    return propertyMap;
+  }
+
+  /**
+   * Add a property value to this instance.
+   *
+   * @param key    the property key
+   * @param value  the property value
+   */
+  public void putProperty(String key, String value) {
+    removeInstanceData(key);
+    ViewInstancePropertyEntity viewInstancePropertyEntity = new ViewInstancePropertyEntity();
+    viewInstancePropertyEntity.setViewName(viewName);
+    viewInstancePropertyEntity.setViewInstanceName(name);
+    viewInstancePropertyEntity.setName(key);
+    viewInstancePropertyEntity.setValue(value);
+    viewInstancePropertyEntity.setViewInstanceEntity(this);
+    properties.add(viewInstancePropertyEntity);
+  }
+
+  /**
+   * Remove the property identified by the given key from this instance.
+   *
+   * @param key  the key
+   */
+  public void removeProperty(String key) {
+    ViewInstancePropertyEntity entity = getProperty(key);
+    if (entity != null) {
+      properties.remove(entity);
+    }
+  }
+
+  /**
+   * Get the instance property entity for the given key.
+   *
+   * @param key  the key
+   *
+   * @return the instance property entity identified by the given key
+   */
+  public ViewInstancePropertyEntity getProperty(String key) {
+    for (ViewInstancePropertyEntity viewInstancePropertyEntity : properties) {
+      if (viewInstancePropertyEntity.getName().equals(key)) {
+        return viewInstancePropertyEntity;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Set the collection of instance property entities.
+   *
+   * @param properties  the collection of instance property entities
+   */
+  public void setProperties(Collection<ViewInstancePropertyEntity> properties) {
+    this.properties = properties;
+  }
+
+  /**
+   * Get the instance data.
+   *
+   * @return the instance data
+   */
+  public Collection<ViewInstanceDataEntity> getData() {
+    return data;
+  }
+
+  /**
+   * Set the collection of instance data entities.
+   *
+   * @param data  the collection of instance data entities
+   */
+  public void setData(Collection<ViewInstanceDataEntity> data) {
+    this.data = data;
+  }
+
+  /**
+   * Get the view instance application data.
+   *
+   * @return the view instance application data map
+   */
+  public Map<String, String> getInstanceDataMap() {
+    Map<String, String> applicationData = new HashMap<String, String>();
+
+    for (ViewInstanceDataEntity viewInstanceDataEntity : data) {
+      applicationData.put(viewInstanceDataEntity.getName(), viewInstanceDataEntity.getValue());
+    }
+    return applicationData;
+  }
+
+  /**
+   * Associate the given instance data value with the given key.
+   *
+   * @param key    the key
+   * @param value  the value
+   */
+  public void putInstanceData(String key, String value) {
+    removeInstanceData(key);
+    ViewInstanceDataEntity viewInstanceDataEntity = new ViewInstanceDataEntity();
+    viewInstanceDataEntity.setViewName(viewName);
+    viewInstanceDataEntity.setViewInstanceName(name);
+    viewInstanceDataEntity.setName(key);
+    viewInstanceDataEntity.setValue(value);
+    viewInstanceDataEntity.setViewInstanceEntity(this);
+    data.add(viewInstanceDataEntity);
+  }
+
+  /**
+   * Remove the instance data entity associated with the given key.
+   *
+   * @param key  the key
+   */
+  public void removeInstanceData(String key) {
+    ViewInstanceDataEntity entity = getInstanceData(key);
+    if (entity != null) {
+      data.remove(entity);
+    }
+  }
+
+  /**
+   * Get the instance data entity for the given key.
+   *
+   * @param key  the key
+   *
+   * @return the instance data entity associated with the given key
+   */
+  public ViewInstanceDataEntity getInstanceData(String key) {
+    for (ViewInstanceDataEntity viewInstanceDataEntity : data) {
+      if (viewInstanceDataEntity.getName().equals(key)) {
+        return viewInstanceDataEntity;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Get the parent view entity.
+   *
+   * @return the parent view entity
+   */
+  public ViewEntity getViewEntity() {
+    return view;
+  }
+
+  /**
+   * Set the parent view entity.
+   *
+   * @param view  the parent view entity
+   */
+  public void setViewEntity(ViewEntity view) {
+    this.view = view;
+  }
+
+  /**
+   * Get the associated configuration.
+   *
+   * @return the configuration
+   */
+  public InstanceConfig getConfiguration() {
+    return instanceConfig;
+  }
+
+  /**
+   * Add a resource provider for the given resource type.
+   *
+   * @param type      the resource type
+   * @param provider  the resource provider
+   */
+  public void addResourceProvider(Resource.Type type, ResourceProvider provider) {
+    resourceProviders.put(type, provider);
+  }
+
+  /**
+   * Get the resource provider for the given resource type.
+   *
+   * @param type  the resource type
+   *
+   * @return the resource provider
+   */
+  public ResourceProvider getResourceProvider(Resource.Type type) {
+    return resourceProviders.get(type);
+  }
+
+  /**
+   * Get the resource provider for the given resource type name (scoped to this view).
+   *
+   * @param type  the resource type name
+   *
+   * @return the resource provider
+   */
+  public ResourceProvider getResourceProvider(String type) {
+    String typeName = view.getName() + "/" + type;
+    return resourceProviders.get(Resource.Type.valueOf(typeName));
+  }
+
+  /**
+   * Add a service for the given plural resource name.
+   *
+   * @param pluralName  the plural resource name
+   * @param service     the service
+   */
+  public void addService(String pluralName, Object service) {
+    services.put(pluralName, service);
+  }
+
+  /**
+   * Get the service associated with the given plural resource name.
+   *
+   * @param pluralName  the plural resource name
+   *
+   * @return the service associated with the given name
+   */
+  public Object getService(String pluralName) {
+    return services.get(pluralName);
+  }
+
+  /**
+   * Get the context path for the UI for this view.
+   *
+   * @return the context path
+   */
+  public String getContextPath() {
+    return getContextPath(view.getName(), getName());
+  }
+
+  /**
+   * Get the context path for a view instance with the given names.
+   *
+   * @param viewName          the view name
+   * @param viewInstanceName  the instance name
+   *
+   * @return the context path
+   */
+  public static String getContextPath(String viewName, String viewInstanceName) {
+    return VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + viewInstanceName;
+  }
+}

+ 99 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityPK.java

@@ -0,0 +1,99 @@
+/**
+ * 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.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for ViewInstanceEntity.
+ */
+public class ViewInstanceEntityPK {
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewName;
+
+  /**
+   * The instance name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String name;
+
+
+  // ----- ViewInstanceEntityPK ----------------------------------------------
+
+  /**
+   * Get the name of the associated view.
+   *
+   * @return view name
+   */
+  public String getViewName() {
+    return viewName;
+  }
+
+  /**
+   * Set the name of the associated view.
+   *
+   * @param viewName  view name
+   */
+  public void setViewName(String viewName) {
+    this.viewName = viewName;
+  }
+
+  /**
+   * Get the name of the instance.
+   *
+   * @return instance name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of the instance.
+   *
+   * @param name  instance name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewInstanceEntityPK that = (ViewInstanceEntityPK) o;
+
+    return this.viewName.equals(that.viewName) &&
+        this.name.equals(that.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * viewName.hashCode() + name.hashCode();
+  }
+}

+ 168 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstancePropertyEntity.java

@@ -0,0 +1,168 @@
+/**
+ * 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.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Represents a property of a View instance.
+ */
+@javax.persistence.IdClass(ViewInstancePropertyEntityPK.class)
+@Table(name = "viewinstanceproperty")
+@Entity
+public class ViewInstancePropertyEntity {
+
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+  private String viewName;
+
+  /**
+   * The view instance name.
+   */
+  @Id
+  @Column(name = "view_instance_name", nullable = false, insertable = false, updatable = false)
+  private String viewInstanceName;
+
+  /**
+   * The property key.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false)
+  private String name;
+
+  /**
+   * The property value.
+   */
+  @Column
+  @Basic
+  private String value;
+
+  /**
+   * The view instance entity.
+   */
+  @ManyToOne
+  @JoinColumns({
+      @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false),
+      @JoinColumn(name = "view_instance_name", referencedColumnName = "name", nullable = false)
+  })
+  private ViewInstanceEntity viewInstance;
+
+
+  // ----- ViewInstancePropertyEntity ----------------------------------------
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Get the view instance name.
+   *
+   * @return the view instance name
+   */
+  public String getViewInstanceName() {
+    return viewInstanceName;
+  }
+
+  /**
+   * Set the view instance name.
+   *
+   * @param viewInstanceName  the view instance name
+   */
+  public void setViewInstanceName(String viewInstanceName) {
+    this.viewInstanceName = viewInstanceName;
+  }
+
+  /**
+   * Get the property name.
+   *
+   * @return the property name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the property name.
+   *
+   * @param name  the property name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Get the property value.
+   *
+   * @return the property value
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * Set the property value.
+   *
+   * @param value  the property value
+   */
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Get the parent instance entity.
+   *
+   * @return the parent instance entity
+   */
+  public ViewInstanceEntity getViewInstanceEntity() {
+    return viewInstance;
+  }
+
+  /**
+   * Set the parent instance entity.
+   *
+   * @param viewInstance  the parent instance entity
+   */
+  public void setViewInstanceEntity(ViewInstanceEntity viewInstance) {
+    this.viewInstance = viewInstance;
+  }
+}

+ 123 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstancePropertyEntityPK.java

@@ -0,0 +1,123 @@
+/**
+ * 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.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for ViewInstanceDataEntity.
+ */
+public class ViewInstancePropertyEntityPK {
+
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewName;
+
+  /**
+   * The view instance name.
+   */
+  @Id
+  @Column(name = "view_instance_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewInstanceName;
+
+  /**
+   * The property name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String name;
+
+  /**
+   * Get the name of the associated view.
+   *
+   * @return view name
+   */
+  public String getViewName() {
+    return viewName;
+  }
+
+  /**
+   * Set the name of the associated view.
+   *
+   * @param viewName  view name
+   */
+  public void setViewName(String viewName) {
+    this.viewName = viewName;
+  }
+
+  /**
+   * Get the view instance name.
+   *
+   * @return the instance name
+   */
+  public String getViewInstanceName() {
+    return viewInstanceName;
+  }
+
+  /**
+   * Set the view instance name.
+   *
+   * @param viewInstanceName  the instance name
+   */
+  public void setViewInstanceName(String viewInstanceName) {
+    this.viewInstanceName = viewInstanceName;
+  }
+
+  /**
+   * Get the name of the host group.
+   *
+   * @return host group name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of the host group.
+   *
+   * @param name  host group name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewInstancePropertyEntityPK that = (ViewInstancePropertyEntityPK) o;
+
+    return this.viewName.equals(that.viewName) &&
+        this.viewInstanceName.equals(that.viewInstanceName) &&
+        this.name.equals(that.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * viewName.hashCode() + viewInstanceName.hashCode() + name.hashCode();
+  }
+}

+ 157 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java

@@ -0,0 +1,157 @@
+/**
+ * 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.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+/**
+ * Represents a parameter of a View.
+ */
+@javax.persistence.IdClass(ViewParameterEntityPK.class)
+@Table(name = "viewparameter")
+@Entity
+public class ViewParameterEntity {
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+  private String viewName;
+
+  /**
+   * The parameter name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false)
+  private String name;
+
+  /**
+   * The parameter description.
+   */
+  @Column
+  @Basic
+  private String description;
+
+  /**
+   * Indicates whether or not the parameter is required.
+   */
+  @Column
+  @Basic
+  private char required;
+
+  @ManyToOne
+  @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false)
+  private ViewEntity view;
+
+
+  // ----- ViewParameterEntity -----------------------------------------------
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Get the parameter name.
+   *
+   * @return the parameter name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the parameter name.
+   *
+   * @param name  the parameter name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Get the parameter description.
+   *
+   * @return the parameter description
+   */
+  public String getDescription() {
+    return description;
+  }
+
+  /**
+   * Set the parameter description.
+   *
+   * @param description  the parameter description
+   */
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  /**
+   * Determine whether or not the parameter is required.
+   *
+   * @return true if the parameter is required
+   */
+  public boolean isRequired() {
+    return required == 'y' || required == 'Y';
+  }
+
+  /**
+   * Set the flag which indicate whether or not the parameter is required.
+   *
+   * @param required  the required flag; true if the parameter is required
+   */
+  public void setRequired(boolean required) {
+    this.required = (required ? 'Y' : 'N');
+  }
+
+  /**
+   * Get the associated view entity.
+   *
+   * @return the view entity
+   */
+  public ViewEntity getViewEntity() {
+    return view;
+  }
+
+  /**
+   * Set the associated view entity.
+   *
+   * @param view the view entity
+   */
+  public void setViewEntity(ViewEntity view) {
+    this.view = view;
+  }
+}

+ 99 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntityPK.java

@@ -0,0 +1,99 @@
+/**
+ * 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.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for ViewParameterEntity.
+ */
+public class ViewParameterEntityPK {
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewName;
+
+  /**
+   * The parameter name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String name;
+
+
+  // ----- ViewParameterEntityPK ---------------------------------------------
+
+  /**
+   * Get the name of the associated view.
+   *
+   * @return view name
+   */
+  public String getViewName() {
+    return viewName;
+  }
+
+  /**
+   * Set the name of the associated view.
+   *
+   * @param viewName  view name
+   */
+  public void setViewName(String viewName) {
+    this.viewName = viewName;
+  }
+
+  /**
+   * Get the name of the parameter.
+   *
+   * @return parameter name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of the parameter.
+   *
+   * @param name  parameter name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewParameterEntityPK that = (ViewParameterEntityPK) o;
+
+    return this.viewName.equals(that.viewName) &&
+        this.name.equals(that.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * viewName.hashCode() + name.hashCode();
+  }
+}

+ 266 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewResourceEntity.java

@@ -0,0 +1,266 @@
+/**
+ * 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.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Represents a resource of a View.
+ */
+@javax.persistence.IdClass(ViewResourceEntityPK.class)
+@Table(name = "viewresource")
+@Entity
+public class ViewResourceEntity {
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = false, updatable = false)
+  private String viewName;
+
+  /**
+   * The resource name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false)
+  private String name;
+
+  /**
+   * The plural name of the resource.
+   */
+  @Column(name = "plural_name")
+  @Basic
+  private String pluralName;
+
+  /**
+   * The id property of the resource.
+   */
+  @Column(name = "id_property")
+  @Basic
+  private String idProperty;
+
+  /**
+   * The list of sub resource names.
+   */
+  @Column(name = "subResource_names")
+  @Basic
+  private String subResourceNames;
+
+  /**
+   * The resource provider class name.
+   */
+  @Column
+  @Basic
+  private String provider;
+
+  /**
+   * The resource service class name.
+   */
+  @Column
+  @Basic
+  private String service;
+
+  /**
+   * The resource class name.
+   */
+  @Column
+  @Basic
+  private String resource;
+
+  /**
+   * The view entity.
+   */
+  @ManyToOne
+  @JoinColumn(name = "view_name", referencedColumnName = "view_name", nullable = false)
+  private ViewEntity view;
+
+
+  // ----- ViewResourceEntity ------------------------------------------------
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Get the resource name.
+   *
+   * @return the resource name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the resource name.
+   *
+   * @param name  the resource name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Get the resource plural name.
+   *
+   * @return the resource plural name
+   */
+  public String getPluralName() {
+    return pluralName;
+  }
+
+  /**
+   * Set the resource plural name.
+   *
+   * @param pluralName  the plural name
+   */
+  public void setPluralName(String pluralName) {
+    this.pluralName = pluralName;
+  }
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Get the sub-resource names.
+   *
+   * @return the sub resource names
+   */
+  public Collection<String> getSubResourceNames() {
+    return Arrays.asList(subResourceNames.split("\\s*,\\s*"));
+  }
+
+  /**
+   * Set the sub-resource names.
+   *
+   * @param subResourceNames  the sub-resource names
+   */
+  public void setSubResourceNames(Collection<String> subResourceNames) {
+    String s = subResourceNames.toString();
+    this.subResourceNames = subResourceNames.size() > 0 ? s.substring(1, s.length()-1) : null;
+  }
+
+  /**
+   * Get the resource provider class name.
+   *
+   * @return the resource provider class name.
+   */
+  public String getProvider() {
+    return provider;
+  }
+
+  /**
+   * Set the resource provider class name.
+   *
+   * @param provider  the resource provider class name.
+   */
+  public void setProvider(String provider) {
+    this.provider = provider;
+  }
+
+  /**
+   * Get the resource service class name.
+   *
+   * @return the resource service class name
+   */
+  public String getService() {
+    return service;
+  }
+
+  /**
+   * Set the resource service class name.
+   *
+   * @param service  the resource service class name
+   */
+  public void setService(String service) {
+    this.service = service;
+  }
+
+  /**
+   * Get the resource class name.
+   *
+   * @return the resource class name
+   */
+  public String getResource() {
+    return resource;
+  }
+
+  /**
+   * Set the resource class name.
+   *
+   * @param resource  the resource class name
+   */
+  public void setResource(String resource) {
+    this.resource = resource;
+  }
+
+  /**
+   * Get the parent view entity.
+   *
+   * @return the view entity
+   */
+  public ViewEntity getViewEntity() {
+    return view;
+  }
+
+  /**
+   * Set the parent view entity.
+   *
+   * @param view  the parent view entity
+   */
+  public void setViewEntity(ViewEntity view) {
+    this.view = view;
+  }
+}

+ 99 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewResourceEntityPK.java

@@ -0,0 +1,99 @@
+/**
+ * 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.Column;
+import javax.persistence.Id;
+
+/**
+ * Composite primary key for ViewResourceEntity.
+ */
+public class ViewResourceEntityPK {
+  /**
+   * The view name.
+   */
+  @Id
+  @Column(name = "view_name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String viewName;
+
+  /**
+   * The resource name.
+   */
+  @Id
+  @Column(name = "name", nullable = false, insertable = true, updatable = false, length = 100)
+  private String name;
+
+
+  // ----- ViewResourceEntityPK ----------------------------------------------
+
+  /**
+   * Get the name of the associated view.
+   *
+   * @return view name
+   */
+  public String getViewName() {
+    return viewName;
+  }
+
+  /**
+   * Set the name of the associated view.
+   *
+   * @param viewName  view name
+   */
+  public void setViewName(String viewName) {
+    this.viewName = viewName;
+  }
+
+  /**
+   * Get the name of the resource.
+   *
+   * @return resource name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Set the name of the resource.
+   *
+   * @param name  resource name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ViewResourceEntityPK that = (ViewResourceEntityPK) o;
+
+    return this.viewName.equals(that.viewName) &&
+        this.name.equals(that.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return 31 * viewName.hashCode() + name.hashCode();
+  }
+}

+ 41 - 11
ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java

@@ -19,6 +19,7 @@
 package org.apache.ambari.server.view;
 
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.view.ResourceProvider;
 import org.apache.ambari.view.URLStreamProvider;
 import org.apache.ambari.view.ViewContext;
@@ -42,7 +43,12 @@ public class ViewContextImpl implements ViewContext {
   /**
    * The associated view definition.
    */
-  private final ViewInstanceDefinition viewInstanceDefinition;
+  private final ViewInstanceEntity viewInstanceEntity;
+
+  /**
+   * The view registry.
+   */
+  private final ViewRegistry viewRegistry;
 
   /**
    * The available stream provider.
@@ -53,13 +59,15 @@ public class ViewContextImpl implements ViewContext {
   // ---- Constructors -------------------------------------------------------
 
   /**
-   * Construct a view context from the given view definition.
+   * Construct a view context from the given view entity.
    *
-   * @param viewInstanceDefinition  the view definition
+   * @param viewInstanceEntity  the view entity
+   * @param viewRegistry        the view registry
    */
-  public ViewContextImpl(ViewInstanceDefinition viewInstanceDefinition) {
-    this.viewInstanceDefinition = viewInstanceDefinition;
-    this.streamProvider         = ViewURLStreamProvider.getProvider();
+  public ViewContextImpl(ViewInstanceEntity viewInstanceEntity, ViewRegistry viewRegistry) {
+    this.viewInstanceEntity = viewInstanceEntity;
+    this.viewRegistry       = viewRegistry;
+    this.streamProvider     = ViewURLStreamProvider.getProvider();
   }
 
 
@@ -67,27 +75,49 @@ public class ViewContextImpl implements ViewContext {
 
   @Override
   public String getViewName() {
-    return viewInstanceDefinition.getViewDefinition().getName();
+    return viewInstanceEntity.getViewName();
   }
 
   @Override
   public String getInstanceName() {
-    return viewInstanceDefinition.getName();
+    return viewInstanceEntity.getName();
   }
 
   @Override
   public Map<String, String> getProperties() {
-    return viewInstanceDefinition.getProperties();
+    return Collections.unmodifiableMap(viewInstanceEntity.getPropertyMap());
+  }
+
+  @Override
+  public void putInstanceData(String key, String value) {
+    viewInstanceEntity.putInstanceData(key, value);
+    viewRegistry.updateViewInstance(viewInstanceEntity);
+  }
+
+  @Override
+  public String getInstanceData(String key) {
+    return viewInstanceEntity.getInstanceDataMap().get(key);
+  }
+
+  @Override
+  public Map<String, String> getInstanceData() {
+    return Collections.unmodifiableMap(viewInstanceEntity.getInstanceDataMap());
+  }
+
+  @Override
+  public void removeInstanceData(String key) {
+    viewInstanceEntity.removeInstanceData(key);
+    viewRegistry.updateViewInstance(viewInstanceEntity);
   }
 
   @Override
   public String getAmbariProperty(String key) {
-    return viewInstanceDefinition.getViewDefinition().getAmbariProperty(key);
+    return viewInstanceEntity.getViewEntity().getAmbariProperty(key);
   }
 
   @Override
   public ResourceProvider<?> getResourceProvider(String type) {
-    return viewInstanceDefinition.getResourceProvider(type);
+    return viewInstanceEntity.getResourceProvider(type);
   }
 
   @Override

+ 7 - 5
ambari-server/src/main/java/org/apache/ambari/server/view/ViewExternalSubResourceProvider.java

@@ -29,6 +29,8 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -67,7 +69,7 @@ public class ViewExternalSubResourceProvider extends AbstractResourceProvider {
   /**
    * The associated view definition.
    */
-  private final ViewDefinition viewDefinition;
+  private final ViewEntity viewDefinition;
 
 
   // ----- Constructors ------------------------------------------------------
@@ -78,7 +80,7 @@ public class ViewExternalSubResourceProvider extends AbstractResourceProvider {
    * @param type            the resource type
    * @param viewDefinition  the associated view definition
    */
-  public ViewExternalSubResourceProvider(Resource.Type type, ViewDefinition viewDefinition) {
+  public ViewExternalSubResourceProvider(Resource.Type type, ViewEntity viewDefinition) {
     super(_getPropertyIds(), _getKeyPropertyIds(type));
 
     this.type           = type;
@@ -100,12 +102,12 @@ public class ViewExternalSubResourceProvider extends AbstractResourceProvider {
 
     Set<Resource> resourceSet = new HashSet<Resource>();
 
-    Set<ViewInstanceDefinition> instanceDefinitions = new HashSet<ViewInstanceDefinition>();
+    Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();
 
     Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
     int size = propertyMaps.size();
 
-    Collection<ViewInstanceDefinition> viewInstanceDefinitions = viewDefinition.getInstanceDefinitions();
+    Collection<ViewInstanceEntity> viewInstanceDefinitions = viewDefinition.getInstances();
     if (size == 0) {
       instanceDefinitions.addAll(viewInstanceDefinitions);
     } else {
@@ -120,7 +122,7 @@ public class ViewExternalSubResourceProvider extends AbstractResourceProvider {
       }
     }
 
-    for (ViewInstanceDefinition viewInstanceDefinition : instanceDefinitions) {
+    for (ViewInstanceEntity viewInstanceDefinition : instanceDefinitions) {
       for (String resourceName : resourceNames) {
         ResourceImpl resource = new ResourceImpl(type);
         resource.setProperty(VIEW_NAME_PROPERTY_ID, viewDefinition.getName());

+ 0 - 193
ambari-server/src/main/java/org/apache/ambari/server/view/ViewInstanceDefinition.java

@@ -1,193 +0,0 @@
-/**
- * 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;
-
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.view.configuration.InstanceConfig;
-import org.apache.ambari.view.ResourceProvider;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Provides access to the attributes of a view instance.
- */
-public class ViewInstanceDefinition {
-  /**
-   * The prefix for every view instance context path.
-   */
-  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
-
-  /**
-   * The associated configuration.
-   */
-  private final InstanceConfig instanceConfig;
-
-  /**
-   * The parent view definition.
-   */
-  private final ViewDefinition viewDefinition;
-
-  /**
-   * The view instance properties.
-   */
-  private final Map<String, String> properties = new HashMap<String, String>();
-
-  /**
-   * The mapping of resource type to resource provider.
-   */
-  private final Map<Resource.Type, ResourceProvider> resourceProviders = new HashMap<Resource.Type, ResourceProvider>();
-
-  /**
-   * The mapping of the resource plural name to service.
-   */
-  private final Map<String, Object> services = new HashMap<String, Object>();
-
-  /**
-   * The context path for the view web app.
-   */
-  private final String contextPath;
-
-
-  // ----- Constructors ------------------------------------------------------
-
-  /**
-   * Construct a view instance definition.
-   *
-   * @param viewDefinition  the parent view definition
-   * @param instanceConfig  the associated configuration
-   */
-  public ViewInstanceDefinition(ViewDefinition viewDefinition, InstanceConfig instanceConfig) {
-    this.instanceConfig = instanceConfig;
-    this.viewDefinition = viewDefinition;
-    this.contextPath    = VIEWS_CONTEXT_PATH_PREFIX + viewDefinition.getName() + "/" + instanceConfig.getName();
-  }
-
-
-  // ----- ViewInstanceDefinition --------------------------------------------
-
-  /**
-   * Get the parent view definition.
-   *
-   * @return the parent view definition
-   */
-  public ViewDefinition getViewDefinition() {
-    return viewDefinition;
-  }
-
-  /**
-   * Get the associated configuration.
-   *
-   * @return the configuration
-   */
-  public InstanceConfig getConfiguration() {
-    return instanceConfig;
-  }
-
-  /**
-   * Get the view instance name.
-   *
-   * @return the instance name
-   */
-  public String getName() {
-    return instanceConfig.getName();
-  }
-
-  /**
-   * Add a view instance property.
-   *
-   * @param key    the property key
-   * @param value  the property value
-   */
-  public void addProperty(String key, String value) {
-    properties.put(key, value);
-  }
-
-  /**
-   * Get the view instance properties.
-   *
-   * @return the view instance properties
-   */
-  public Map<String, String> getProperties() {
-    return properties;
-  }
-
-  /**
-   * Add a service for the given plural resource name.
-   *
-   * @param pluralName  the plural resource name
-   * @param service     the service
-   */
-  public void addService(String pluralName, Object service) {
-    services.put(pluralName, service);
-  }
-
-  /**
-   * Get the service associated with the given plural resource name.
-   *
-   * @param pluralName  the plural resource name
-   *
-   * @return the service associated with the given name
-   */
-  public Object getService(String pluralName) {
-    return services.get(pluralName);
-  }
-
-  /**
-   * Add a resource provider for the given resource type.
-   *
-   * @param type      the resource type
-   * @param provider  the resource provider
-   */
-  public void addResourceProvider(Resource.Type type, ResourceProvider provider) {
-    resourceProviders.put(type, provider);
-  }
-
-  /**
-   * Get the resource provider for the given resource type.
-   *
-   * @param type  the resource type
-   *
-   * @return the resource provider
-   */
-  public ResourceProvider getResourceProvider(Resource.Type type) {
-    return resourceProviders.get(type);
-  }
-
-  /**
-   * Get the resource provider for the given resource type name (scoped to this view).
-   *
-   * @param type  the resource type name
-   *
-   * @return the resource provider
-   */
-  public ResourceProvider getResourceProvider(String type) {
-    String typeName = viewDefinition.getName() + "/" + type;
-    return resourceProviders.get(Resource.Type.valueOf(typeName));
-  }
-
-  /**
-   * Get the context path for the UI for this view.
-   *
-   * @return the context path
-   */
-  public String getContextPath() {
-    return contextPath;
-  }
-}

+ 2 - 1
ambari-server/src/main/java/org/apache/ambari/server/view/ViewProviderModule.java

@@ -22,6 +22,7 @@ import org.apache.ambari.server.controller.spi.PropertyProvider;
 import org.apache.ambari.server.controller.spi.ProviderModule;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.orm.entities.ViewEntity;
 
 import java.util.HashMap;
 import java.util.List;
@@ -89,7 +90,7 @@ public class ViewProviderModule implements ProviderModule {
     Map<Resource.Type, ResourceProvider> resourceProviders = new HashMap<Resource.Type, ResourceProvider>();
 
     ViewRegistry registry = ViewRegistry.getInstance();
-    for (ViewDefinition definition : registry.getDefinitions()) {
+    for (ViewEntity definition : registry.getDefinitions()) {
       for (Resource.Type type : definition.getViewResourceTypes()){
         ResourceProvider provider = definition.getResourceProvider(type);
         resourceProviders.put(type, provider);

+ 247 - 68
ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.view;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
+import com.google.inject.Inject;
 import com.google.inject.Injector;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
@@ -28,7 +29,14 @@ import org.apache.ambari.server.api.services.ViewExternalSubResourceService;
 import org.apache.ambari.server.api.services.ViewSubResourceService;
 import org.apache.ambari.server.configuration.Configuration;
 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.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewParameterEntity;
+import org.apache.ambari.server.orm.entities.ViewResourceEntity;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
+import org.apache.ambari.server.view.configuration.ParameterConfig;
 import org.apache.ambari.server.view.configuration.PropertyConfig;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
 import org.apache.ambari.server.view.configuration.ViewConfig;
@@ -65,12 +73,12 @@ public class ViewRegistry {
   /**
    * Mapping of view names to view definitions.
    */
-  private Map<String, ViewDefinition> viewDefinitions = new HashMap<String, ViewDefinition>();
+  private Map<String, ViewEntity> viewDefinitions = new HashMap<String, ViewEntity>();
 
   /**
    * Mapping of view instances to view definition and instance name.
    */
-  private Map<ViewDefinition, Map<String, ViewInstanceDefinition>> viewInstanceDefinitions = new HashMap<ViewDefinition, Map<String, ViewInstanceDefinition>>();
+  private Map<ViewEntity, Map<String, ViewInstanceEntity>> viewInstanceDefinitions = new HashMap<ViewEntity, Map<String, ViewInstanceEntity>>();
 
   /**
    * Mapping of view names to sub-resources.
@@ -87,6 +95,28 @@ public class ViewRegistry {
    */
   protected final static Logger LOG = LoggerFactory.getLogger(ViewRegistry.class);
 
+  /**
+   * View data access object.
+   */
+  private static ViewDAO viewDAO;
+
+  /**
+   * View instance data access object.
+   */
+  private static ViewInstanceDAO instanceDAO;
+
+  /**
+   * Static initialization of DAO.
+   *
+   * @param vDAO  view data access object
+   * @param iDAO  view instance data access object
+   */
+  @Inject
+  public static void init(ViewDAO vDAO, ViewInstanceDAO iDAO) {
+    viewDAO     = vDAO;
+    instanceDAO = iDAO;
+  }
+
 
   // ----- Constructors ------------------------------------------------------
 
@@ -104,7 +134,7 @@ public class ViewRegistry {
    *
    * @return the collection of view definitions
    */
-  public Collection<ViewDefinition> getDefinitions() {
+  public Collection<ViewEntity> getDefinitions() {
     return viewDefinitions.values();
   }
 
@@ -115,7 +145,7 @@ public class ViewRegistry {
    *
    * @return the view definition for the given name
    */
-  public ViewDefinition getDefinition(String viewName) {
+  public ViewEntity getDefinition(String viewName) {
     return viewDefinitions.get(viewName);
   }
 
@@ -124,7 +154,7 @@ public class ViewRegistry {
    *
    * @param definition  the definition
    */
-  public void addDefinition(ViewDefinition definition) {
+  public void addDefinition(ViewEntity definition) {
     viewDefinitions.put(definition.getName(), definition);
   }
 
@@ -135,7 +165,7 @@ public class ViewRegistry {
    *
    * @return the collection of view instances for the view definition
    */
-  public Collection<ViewInstanceDefinition> getInstanceDefinitions(ViewDefinition definition) {
+  public Collection<ViewInstanceEntity> getInstanceDefinitions(ViewEntity definition) {
     return definition == null ? null : viewInstanceDefinitions.get(definition).values();
   }
 
@@ -147,8 +177,8 @@ public class ViewRegistry {
    *
    * @return the view instance definition for the given view and instance name
    */
-  public ViewInstanceDefinition getInstanceDefinition(String viewName, String instanceName) {
-    Map<String, ViewInstanceDefinition> viewInstanceDefinitionMap =
+  public ViewInstanceEntity getInstanceDefinition(String viewName, String instanceName) {
+    Map<String, ViewInstanceEntity> viewInstanceDefinitionMap =
         viewInstanceDefinitions.get(getDefinition(viewName));
 
     return viewInstanceDefinitionMap == null ? null : viewInstanceDefinitionMap.get(instanceName);
@@ -160,15 +190,28 @@ public class ViewRegistry {
    * @param definition          the owning view definition
    * @param instanceDefinition  the instance definition
    */
-  public void addInstanceDefinition(ViewDefinition definition, ViewInstanceDefinition instanceDefinition) {
-    Map<String, ViewInstanceDefinition> instanceDefinitions = viewInstanceDefinitions.get(definition);
+  public void addInstanceDefinition(ViewEntity definition, ViewInstanceEntity instanceDefinition) {
+    Map<String, ViewInstanceEntity> instanceDefinitions = viewInstanceDefinitions.get(definition);
     if (instanceDefinitions == null) {
-      instanceDefinitions = new HashMap<String, ViewInstanceDefinition>();
+      instanceDefinitions = new HashMap<String, ViewInstanceEntity>();
       viewInstanceDefinitions.put(definition, instanceDefinitions);
     }
     instanceDefinitions.put(instanceDefinition.getName(), instanceDefinition);
   }
 
+  /**
+   * Remove an instance definition for the given view definition.
+   *
+   * @param definition    the owning view definition
+   * @param instanceName  the instance name
+   */
+  public void removeInstanceDefinition(ViewEntity definition, String instanceName) {
+    Map<String, ViewInstanceEntity> instanceDefinitions = viewInstanceDefinitions.get(definition);
+    if (instanceDefinitions != null) {
+      instanceDefinitions.remove(instanceName);
+    }
+  }
+
   /**
    * Get the view registry singleton.
    *
@@ -191,7 +234,7 @@ public class ViewRegistry {
 
     if (subResourceDefinitions == null) {
       subResourceDefinitions = new HashSet<SubResourceDefinition>();
-      ViewDefinition definition = getDefinition(viewName);
+      ViewEntity definition = getDefinition(viewName);
       if (definition != null) {
         for (Resource.Type type : definition.getViewResourceTypes()) {
           subResourceDefinitions.add(new SubResourceDefinition(type));
@@ -207,12 +250,12 @@ public class ViewRegistry {
    *
    * @param configuration  Ambari configuration
    */
-  public static Set<ViewInstanceDefinition> readViewArchives(Configuration configuration) {
+  public Set<ViewInstanceEntity> readViewArchives(Configuration configuration) {
 
     File   viewDir = configuration.getViewsDir();
     File[] files   = viewDir.listFiles();
 
-    Set<ViewInstanceDefinition> instanceDefinitions = new HashSet<ViewInstanceDefinition>();
+    Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();
 
     if (files != null) {
       for (final File fileEntry : files) {
@@ -224,78 +267,106 @@ public class ViewRegistry {
             JAXBContext    jaxbContext      = JAXBContext.newInstance(ViewConfig.class);
             Unmarshaller   jaxbUnmarshaller = jaxbContext.createUnmarshaller();
             ViewConfig     viewConfig       = (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
-            ViewDefinition viewDefinition   = installView(viewConfig, configuration, cl, fileEntry.getAbsolutePath());
+            ViewEntity viewDefinition       = installView(viewConfig, configuration, cl, fileEntry.getAbsolutePath());
+
+            for (InstanceConfig instanceConfig : viewConfig.getInstances()) {
+              ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
 
-            List<InstanceConfig> instances = viewConfig.getInstances();
+              for (PropertyConfig propertyConfig : instanceConfig.getProperties()) {
+                viewInstanceDefinition.putProperty(propertyConfig.getKey(), propertyConfig.getValue());
+              }
 
-            for (InstanceConfig instanceConfig : instances) {
-              instanceDefinitions.add(installViewInstance(viewDefinition, instanceConfig));
+              _installViewInstance(viewDefinition, viewInstanceDefinition);
+              instanceDefinitions.add(viewInstanceDefinition);
             }
           } catch (Exception e) {
             LOG.error("Caught exception loading view from " + fileEntry.getAbsolutePath(), e);
           }
         }
       }
+      try {
+
+        instanceDefinitions.addAll(persistViews());
+      } catch (ClassNotFoundException e) {
+        LOG.error("Caught exception persisting views.", e);
+      }
     }
     return instanceDefinitions;
   }
 
   /**
-   * Install a view instance described by the given instance configuration
-   * for the view defined by the given view definition.
-   *
-   * @param viewDefinition  the view definition
-   * @param instanceConfig  the instance configuration
-   *
-   * @return the new view instance definition
+   * Install a view instance for the view with the given view name.
    *
-   * @throws ClassNotFoundException if the view classes in the given configuration can not be found
+   * @param instanceEntity  the view instance entity
    */
-  public static ViewInstanceDefinition installViewInstance(ViewDefinition viewDefinition,
-                                                            InstanceConfig instanceConfig)
-      throws ClassNotFoundException {
-
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+  public void installViewInstance(ViewInstanceEntity instanceEntity){
+    String viewName       = instanceEntity.getViewName();
+    ViewEntity viewEntity = getDefinition(viewName);
 
-    List<PropertyConfig> propertyConfigs = instanceConfig.getProperties();
+    if (viewEntity != null) {
+      String instanceName = instanceEntity.getName();
 
-    for (PropertyConfig propertyConfig : propertyConfigs) {
-      viewInstanceDefinition.addProperty(propertyConfig.getKey(), propertyConfig.getValue());
+      if (getInstanceDefinition(viewName, instanceName) == null) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Creating view instance " + viewName + "/" + instanceName);
+        }
+        instanceDAO.create(instanceEntity);
+        try {
+          _installViewInstance(viewEntity, instanceEntity);
+        } catch (ClassNotFoundException e) {
+          LOG.error("Caught exception installing view instance.", e);
+        }
+      }
     }
+  }
 
-    ViewContext viewInstanceContext = new ViewContextImpl(viewInstanceDefinition);
-
-    ViewExternalSubResourceService externalSubResourceService =
-        new ViewExternalSubResourceService(viewDefinition.getExternalResourceType(), viewInstanceDefinition);
-
-    viewInstanceDefinition.addService(ResourceConfig.EXTERNAL_RESOURCE_PLURAL_NAME, externalSubResourceService);
+  /**
+   * Update a view instance for the view with the given view name.
+   *
+   * @param instanceEntity  the view instance entity
+   */
+  public void updateViewInstance(ViewInstanceEntity instanceEntity) {
+    String       viewName   = instanceEntity.getViewName();
+    ViewEntity   viewEntity = getDefinition(viewName);
+
+    if (viewEntity != null) {
+      String instanceName = instanceEntity.getName();
+      ViewInstanceEntity entity = getInstanceDefinition(viewName, instanceName);
+      if (entity != null) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Updating view instance " + viewName + "/" + instanceName);
+        }
 
-    Collection<ViewSubResourceDefinition> resourceDefinitions = viewDefinition.getResourceDefinitions().values();
-    for (ViewSubResourceDefinition resourceDefinition : resourceDefinitions) {
+        entity.setProperties(instanceEntity.getProperties());
+        entity.setData(instanceEntity.getData());
 
-      Resource.Type  type           = resourceDefinition.getType();
-      ResourceConfig resourceConfig = resourceDefinition.getResourceConfiguration();
+        instanceDAO.merge(entity);
+      }
+    }
+  }
 
-      ViewResourceHandler viewResourceService =
-          new ViewSubResourceService(type, viewDefinition.getName(), instanceConfig.getName());
+  /**
+   * Uninstall a view instance for the view with the given view name.
+   *
+   * @param instanceEntity  the view instance entity
+   */
+  public void uninstallViewInstance(ViewInstanceEntity instanceEntity) {
 
-      ClassLoader cl = viewDefinition.getClassLoader();
+    String       viewName   = instanceEntity.getViewName();
+    ViewEntity   viewEntity = getDefinition(viewName);
 
-      Object service = getService(resourceConfig.getServiceClass(cl), viewResourceService, viewInstanceContext);
+    if (viewEntity != null) {
+      String instanceName = instanceEntity.getName();
+      if (getInstanceDefinition(viewName, instanceName) != null) {
 
-      if (resourceConfig.isExternal()) {
-        externalSubResourceService.addResourceService(resourceConfig.getName(), service);
-      } else {
-        viewInstanceDefinition.addService(viewDefinition.getResourceDefinition(type).getPluralName(),service);
-        viewInstanceDefinition.addResourceProvider(type,
-            getProvider(resourceConfig.getProviderClass(cl), viewInstanceContext));
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Deleting view instance " + viewName + "/" + instanceName);
+        }
+        instanceDAO.remove(instanceEntity);
+        viewEntity.removeInstanceDefinition(instanceName);
+        removeInstanceDefinition(viewEntity, instanceName);
       }
     }
-
-    viewDefinition.addInstanceDefinition(viewInstanceDefinition);
-    ViewRegistry.getInstance().addInstanceDefinition(viewDefinition, viewInstanceDefinition);
-
-    return viewInstanceDefinition;
   }
 
   /**
@@ -305,12 +376,12 @@ public class ViewRegistry {
    *
    * @return a web app context
    */
-  public static WebAppContext getWebAppContext(ViewInstanceDefinition viewInstanceDefinition) {
-    ViewDefinition viewDefinition = viewInstanceDefinition.getViewDefinition();
+  public WebAppContext getWebAppContext(ViewInstanceEntity viewInstanceDefinition) {
+    ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
 
-    WebAppContext context = new WebAppContext(viewDefinition.getArchivePath(), viewInstanceDefinition.getContextPath());
+    WebAppContext context = new WebAppContext(viewDefinition.getArchive(), viewInstanceDefinition.getContextPath());
     context.setClassLoader(viewDefinition.getClassLoader());
-    context.setAttribute(ViewContext.CONTEXT_ATTRIBUTE, new ViewContextImpl(viewInstanceDefinition));
+    context.setAttribute(ViewContext.CONTEXT_ATTRIBUTE, new ViewContextImpl(viewInstanceDefinition, this));
     return context;
   }
 
@@ -327,13 +398,28 @@ public class ViewRegistry {
   }
 
   // install a new view definition
-  private static ViewDefinition installView(ViewConfig viewConfig, Configuration ambariConfig,
+  private ViewEntity installView(ViewConfig viewConfig, Configuration ambariConfig,
                                             ClassLoader cl, String archivePath)
       throws ClassNotFoundException, IntrospectionException {
 
-    List<ResourceConfig> resourceConfigurations = viewConfig.getResources();
+    ViewEntity viewDefinition = new ViewEntity(viewConfig, ambariConfig, cl, archivePath);
+
+    List<ParameterConfig> parameterConfigurations = viewConfig.getParameters();
+
+    Collection<ViewParameterEntity> parameters = new HashSet<ViewParameterEntity>();
+    for (ParameterConfig parameterConfiguration : parameterConfigurations) {
+      ViewParameterEntity viewParameterEntity =  new ViewParameterEntity();
 
-    ViewDefinition viewDefinition = new ViewDefinition(viewConfig, ambariConfig, cl, archivePath);
+      viewParameterEntity.setViewName(viewDefinition.getName());
+      viewParameterEntity.setName(parameterConfiguration.getName());
+      viewParameterEntity.setDescription(parameterConfiguration.getDescription());
+      viewParameterEntity.setRequired(parameterConfiguration.isRequired());
+      viewParameterEntity.setViewEntity(viewDefinition);
+      parameters.add(viewParameterEntity);
+    }
+    viewDefinition.setParameters(parameters);
+
+    List<ResourceConfig> resourceConfigurations = viewConfig.getResources();
 
     Resource.Type externalResourceType = viewDefinition.getExternalResourceType();
 
@@ -344,7 +430,19 @@ public class ViewRegistry {
     ResourceInstanceFactoryImpl.addResourceDefinition(externalResourceType,
         new ViewExternalSubResourceDefinition(externalResourceType));
 
+    Collection<ViewResourceEntity> resources = new HashSet<ViewResourceEntity>();
     for (ResourceConfig resourceConfiguration : resourceConfigurations) {
+      ViewResourceEntity viewResourceEntity = new ViewResourceEntity();
+
+      viewResourceEntity.setViewName(viewDefinition.getName());
+      viewResourceEntity.setName(resourceConfiguration.getName());
+      viewResourceEntity.setPluralName(resourceConfiguration.getPluralName());
+      viewResourceEntity.setIdProperty(resourceConfiguration.getIdProperty());
+      viewResourceEntity.setResource(resourceConfiguration.getResource());
+      viewResourceEntity.setService(resourceConfiguration.getService());
+      viewResourceEntity.setProvider(resourceConfiguration.getProvider());
+      viewResourceEntity.setSubResourceNames(resourceConfiguration.getSubResourceNames());
+      viewResourceEntity.setViewEntity(viewDefinition);
 
       ViewSubResourceDefinition resourceDefinition = new ViewSubResourceDefinition(viewDefinition, resourceConfiguration);
       viewDefinition.addResourceDefinition(resourceDefinition);
@@ -361,13 +459,53 @@ public class ViewRegistry {
         String   idProperty = resourceConfiguration.getIdProperty();
 
         viewDefinition.addResourceProvider(type, new ViewSubResourceProvider(type, clazz, idProperty, viewDefinition));
+
+        resources.add(viewResourceEntity);
       }
+      viewDefinition.setResources(resources);
     }
-
-    ViewRegistry.getInstance().addDefinition(viewDefinition);
+    addDefinition(viewDefinition);
     return viewDefinition;
   }
 
+  // install a view instance definition
+  private void _installViewInstance(ViewEntity viewDefinition,
+                                           ViewInstanceEntity viewInstanceDefinition)
+      throws ClassNotFoundException {
+
+    ViewContext viewInstanceContext = new ViewContextImpl(viewInstanceDefinition, this);
+
+    ViewExternalSubResourceService externalSubResourceService =
+        new ViewExternalSubResourceService(viewDefinition.getExternalResourceType(), viewInstanceDefinition);
+
+    viewInstanceDefinition.addService(ResourceConfig.EXTERNAL_RESOURCE_PLURAL_NAME, externalSubResourceService);
+
+    Collection<ViewSubResourceDefinition> resourceDefinitions = viewDefinition.getResourceDefinitions().values();
+    for (ViewSubResourceDefinition resourceDefinition : resourceDefinitions) {
+
+      Resource.Type  type           = resourceDefinition.getType();
+      ResourceConfig resourceConfig = resourceDefinition.getResourceConfiguration();
+
+      ViewResourceHandler viewResourceService =
+          new ViewSubResourceService(type, viewDefinition.getName(), viewInstanceDefinition.getName());
+
+      ClassLoader cl = viewDefinition.getClassLoader();
+
+      Object service = getService(resourceConfig.getServiceClass(cl), viewResourceService, viewInstanceContext);
+
+      if (resourceConfig.isExternal()) {
+        externalSubResourceService.addResourceService(resourceConfig.getName(), service);
+      } else {
+        viewInstanceDefinition.addService(viewDefinition.getResourceDefinition(type).getPluralName(),service);
+        viewInstanceDefinition.addResourceProvider(type,
+            getProvider(resourceConfig.getProviderClass(cl), viewInstanceContext));
+      }
+    }
+
+    viewDefinition.addInstanceDefinition(viewInstanceDefinition);
+    addInstanceDefinition(viewDefinition, viewInstanceDefinition);
+  }
+
   // 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,
@@ -397,4 +535,45 @@ public class ViewRegistry {
     });
     return viewInstanceInjector.getInstance(clazz);
   }
+
+  // make sure that the views in the ambari db match the registry
+  private Set<ViewInstanceEntity> persistViews() throws ClassNotFoundException {
+
+    Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();
+    Set<String> persistedViews = new HashSet<String>();
+
+    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);
+
+        ViewEntity viewDefinition = ViewRegistry.getInstance().viewDefinitions.get(name);
+
+        for (ViewInstanceEntity viewInstanceEntity : viewEntity.getInstances()){
+          if (viewDefinition.getInstanceDefinition(viewInstanceEntity.getName()) == null) {
+            viewInstanceEntity.setViewEntity(viewDefinition);
+            _installViewInstance(viewDefinition, viewInstanceEntity);
+            instanceDefinitions.add(viewInstanceEntity);
+          }
+        }
+      }
+    }
+
+    // persist new views
+    for (ViewEntity definition : viewDefinitions.values() ) {
+      String viewName = definition.getName();
+
+      if (!persistedViews.contains(viewName)) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Creating View " + viewName + ".");
+        }
+        viewDAO.create(definition);
+      }
+    }
+    return instanceDefinitions;
+  }
 }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/view/ViewSubResourceDefinition.java

@@ -21,6 +21,7 @@ package org.apache.ambari.server.view;
 import org.apache.ambari.server.api.resources.BaseResourceDefinition;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
 
 import java.util.HashSet;
@@ -34,7 +35,7 @@ public class ViewSubResourceDefinition extends BaseResourceDefinition {
   /**
    * The associated view definition.
    */
-  private final ViewDefinition viewDefinition;
+  private final ViewEntity viewDefinition;
 
   /**
    * The configuration.
@@ -55,7 +56,7 @@ public class ViewSubResourceDefinition extends BaseResourceDefinition {
    * @param viewDefinition         the view definition
    * @param resourceConfiguration  the resource configuration
    */
-  public ViewSubResourceDefinition(ViewDefinition viewDefinition, ResourceConfig resourceConfiguration) {
+  public ViewSubResourceDefinition(ViewEntity viewDefinition, ResourceConfig resourceConfiguration) {
     super(new Resource.Type(viewDefinition.getQualifiedResourceTypeName(resourceConfiguration.getName())));
 
     this.viewDefinition        = viewDefinition;

+ 11 - 6
ambari-server/src/main/java/org/apache/ambari/server/view/ViewSubResourceProvider.java

@@ -31,6 +31,8 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.view.ReadRequest;
 
 import java.beans.IntrospectionException;
@@ -55,7 +57,7 @@ public class ViewSubResourceProvider extends AbstractResourceProvider {
   private static final String VIEW_NAME_PROPERTY_ID = "view_name";
   private static final String INSTANCE_NAME_PROPERTY_ID = "instance_name";
 
-  private final ViewDefinition viewDefinition;
+  private final ViewEntity viewDefinition;
   private final String pkField;
   private final Resource.Type type;
   private final Map<String, PropertyDescriptor> descriptorMap;
@@ -75,7 +77,7 @@ public class ViewSubResourceProvider extends AbstractResourceProvider {
    *
    * @throws IntrospectionException if an exception occurs during introspection of the resource bean class
    */
-  public ViewSubResourceProvider(Resource.Type type, Class<?> clazz, String pkField, ViewDefinition viewDefinition)
+  public ViewSubResourceProvider(Resource.Type type, Class<?> clazz, String pkField, ViewEntity viewDefinition)
       throws IntrospectionException {
 
     super(discoverPropertyIds(clazz), getKeyPropertyIds(pkField, type));
@@ -120,14 +122,14 @@ public class ViewSubResourceProvider extends AbstractResourceProvider {
 
     Set<String> requestedIds = getRequestPropertyIds(request, predicate);
 
-    Set<ViewInstanceDefinition> instanceDefinitions = new HashSet<ViewInstanceDefinition>();
+    Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();
 
     try {
 
       Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
       int size = propertyMaps.size();
 
-      Collection<ViewInstanceDefinition> viewInstanceDefinitions = viewDefinition.getInstanceDefinitions();
+      Collection<ViewInstanceEntity> viewInstanceDefinitions = viewDefinition.getInstances();
       if (size == 0) {
         instanceDefinitions.addAll(viewInstanceDefinitions);
       } else {
@@ -144,14 +146,17 @@ public class ViewSubResourceProvider extends AbstractResourceProvider {
             instanceDefinitions.addAll(viewInstanceDefinitions);
             break;
           } else {
-            instanceDefinitions.add(viewDefinition.getInstanceDefinition(instanceName));
+            ViewInstanceEntity instanceDefinition = viewDefinition.getInstanceDefinition(instanceName);
+            if (instanceDefinition != null) {
+              instanceDefinitions.add(instanceDefinition);
+            }
           }
         }
       }
 
       Set<Resource> results = new HashSet<Resource>();
       ReadRequest readRequest = new ViewReadRequest(requestedIds, predicate == null ? "" : predicate.toString());
-      for (ViewInstanceDefinition instanceDefinition : instanceDefinitions) {
+      for (ViewInstanceEntity instanceDefinition : instanceDefinitions) {
 
         Set<?> beans = instanceDefinition.getResourceProvider(type).getResources(readRequest);
 

+ 27 - 0
ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ResourceConfig.java

@@ -130,6 +130,33 @@ public class ResourceConfig {
     return subResourceNames == null ? Collections.<String>emptyList() : subResourceNames;
   }
 
+  /**
+   * Get the provider class name.
+   *
+   * @return the provider class name
+   */
+  public String getProvider() {
+    return provider;
+  }
+
+  /**
+   * Get the service class name.
+   *
+   * @return the service class name.
+   */
+  public String getService() {
+    return service;
+  }
+
+  /**
+   * Get the resource class name
+   *
+   * @return the resource classname
+   */
+  public String getResource() {
+    return resource;
+  }
+
   /**
    * Get the resource provider class.
    *

+ 0 - 5
ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java

@@ -67,11 +67,6 @@ public class ViewConfig {
   @XmlElement(name="instance")
   private List<InstanceConfig> instances;
 
-  /**
-   * The mapping of servlet names to URL patterns.
-   */
-  public Map<String, String> servletURLPatternMap = null;
-
   /**
    * Get the unique name.
    *

+ 18 - 0
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -61,6 +61,19 @@ CREATE TABLE hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255)
 CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data VARCHAR(32000) NOT NULL , PRIMARY KEY(blueprint_name, type_name));
 
+CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255) NOT NULL, version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE ambari.viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE ambari.viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
+CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) 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));
+GRANT ALL PRIVILEGES ON TABLE ambari.view TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstancedata TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstance TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstanceproperty TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewparameter TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewresource TO :username;
+
 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);
 ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -97,6 +110,11 @@ ALTER TABLE hostgroup ADD CONSTRAINT FK_hg_blueprint_name FOREIGN KEY (blueprint
 ALTER TABLE hostgroup_component ADD CONSTRAINT FK_hgc_blueprint_name FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup(blueprint_name, name);
 ALTER TABLE blueprint_configuration ADD CONSTRAINT FK_cfg_blueprint_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name);
 ALTER TABLE requestresourcefilter ADD CONSTRAINT FK_reqresfilter_req_id FOREIGN KEY (request_id) REFERENCES request (request_id);
+ALTER TABLE ambari.viewparameter ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewresource ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewinstance ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewinstanceproperty ADD FOREIGN KEY (view_name, view_instance_name) REFERENCES ambari.viewinstance(view_name, name);
+ALTER TABLE ambari.viewinstancedata ADD FOREIGN KEY (view_name, view_instance_name) REFERENCES ambari.viewinstance(view_name, name);
 
 
 INSERT INTO ambari_sequences(sequence_name, value) values ('cluster_id_seq', 1);

+ 11 - 0
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -50,6 +50,12 @@ CREATE TABLE blueprint (blueprint_name VARCHAR2(255) NOT NULL, stack_name VARCHA
 CREATE TABLE hostgroup (blueprint_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, cardinality VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, name));
 CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL , PRIMARY KEY(blueprint_name, type_name));
+CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255) NOT NULL, version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
+CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) 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));
 
 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);
@@ -87,6 +93,11 @@ ALTER TABLE hostgroup ADD CONSTRAINT FK_hg_blueprint_name FOREIGN KEY (blueprint
 ALTER TABLE hostgroup_component ADD CONSTRAINT FK_hgc_blueprint_name FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES hostgroup(blueprint_name, name);
 ALTER TABLE blueprint_configuration ADD CONSTRAINT FK_cfg_blueprint_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name);
 ALTER TABLE requestresourcefilter ADD CONSTRAINT FK_reqresfilter_req_id FOREIGN KEY (request_id) REFERENCES request (request_id);
+ALTER TABLE viewparameter ADD CONSTRAINT FK_viewparameter_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
+ALTER TABLE viewresource ADD CONSTRAINT FK_viewresource_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
+ALTER TABLE viewinstance ADD CONSTRAINT FK_viewinstance_view_name FOREIGN KEY (view_name) REFERENCES viewmain(view_name);
+ALTER TABLE viewinstanceproperty ADD CONSTRAINT FK_viewinstanceproperty_view_name FOREIGN KEY (view_name, view_instance_name) REFERENCES viewinstance(view_name, name);
+ALTER TABLE viewinstancedata ADD CONSTRAINT FK_viewinstancedata_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);

+ 18 - 0
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -127,6 +127,19 @@ GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username;
 
+CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255) NOT NULL, version VARCHAR(255), archive VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE ambari.viewinstancedata (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
+CREATE TABLE ambari.viewinstance (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(view_name, name));
+CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(255) 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));
+GRANT ALL PRIVILEGES ON TABLE ambari.viewmain TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstancedata TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstance TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewinstanceproperty TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewparameter TO :username;
+GRANT ALL PRIVILEGES ON TABLE ambari.viewresource TO :username;
+
 --------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);
 ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -163,6 +176,11 @@ ALTER TABLE ambari.hostgroup ADD CONSTRAINT FK_hg_blueprint_name FOREIGN KEY (bl
 ALTER TABLE ambari.hostgroup_component ADD CONSTRAINT FK_hgc_blueprint_name FOREIGN KEY (blueprint_name, hostgroup_name) REFERENCES ambari.hostgroup (blueprint_name, name);
 ALTER TABLE ambari.blueprint_configuration ADD CONSTRAINT FK_cfg_blueprint_name FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name);
 ALTER TABLE ambari.requestresourcefilter ADD CONSTRAINT FK_reqresfilter_req_id FOREIGN KEY (request_id) REFERENCES ambari.request (request_id);
+ALTER TABLE ambari.viewparameter ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewresource ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewinstance ADD FOREIGN KEY (view_name) REFERENCES ambari.viewmain(view_name);
+ALTER TABLE ambari.viewinstanceproperty ADD FOREIGN KEY (view_name, view_instance_name) REFERENCES ambari.viewinstance(view_name, name);
+ALTER TABLE ambari.viewinstancedata ADD FOREIGN KEY (view_name, view_instance_name) REFERENCES ambari.viewinstance(view_name, name);
 
 
 ---------inserting some data-----------

+ 6 - 0
ambari-server/src/main/resources/META-INF/persistence.xml

@@ -45,6 +45,12 @@
     <class>org.apache.ambari.server.orm.entities.HostGroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostGroupComponentEntity</class>
     <class>org.apache.ambari.server.orm.entities.RequestResourceFilterEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ViewEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ViewInstanceDataEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ViewInstanceEntity</class>
+    <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>
 
     <properties>
       <!--<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/ambari" />-->

+ 3 - 3
ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewExternalSubResourceServiceTest.java

@@ -18,8 +18,8 @@
 package org.apache.ambari.server.api.services;
 
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.view.ViewInstanceDefinition;
-import org.apache.ambari.server.view.ViewInstanceDefinitionTest;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntityTest;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -31,7 +31,7 @@ public class ViewExternalSubResourceServiceTest {
   public void testAddResourceService() throws Exception {
     Resource.Type type = new Resource.Type("resource");
 
-    ViewInstanceDefinition definition = ViewInstanceDefinitionTest.getViewInstanceDefinition();
+    ViewInstanceEntity definition = ViewInstanceEntityTest.getViewInstanceEntity();
     ViewExternalSubResourceService service = new ViewExternalSubResourceService(type, definition);
 
     Object fooService = new Object();

+ 27 - 25
ambari-server/src/test/java/org/apache/ambari/server/view/ViewDefinitionTest.java → ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java

@@ -15,12 +15,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.ambari.server.view;
+package org.apache.ambari.server.orm.entities;
 
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.view.ViewSubResourceDefinition;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
 import org.apache.ambari.server.view.configuration.ResourceConfigTest;
 import org.apache.ambari.server.view.configuration.ViewConfig;
@@ -37,54 +37,56 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
+
 /**
- * ViewDefinition tests.
+ * ViewEntity tests.
  */
-public class ViewDefinitionTest {
+public class ViewEntityTest {
+
 
-  public static ViewDefinition getViewDefinition() throws Exception {
-    return getViewDefinition(ViewConfigTest.getConfig());
+  public static ViewEntity getViewEntity() throws Exception {
+    return getViewEntity(ViewConfigTest.getConfig());
   }
 
-  public static ViewDefinition getViewDefinition(ViewConfig viewConfig) throws Exception {
+  public static ViewEntity getViewEntity(ViewConfig viewConfig) throws Exception {
     Properties properties = new Properties();
     properties.put("p1", "v1");
     properties.put("p2", "v2");
     properties.put("p3", "v3");
 
     Configuration ambariConfig = new Configuration(properties);
-    return new ViewDefinition(viewConfig, ambariConfig, ViewDefinitionTest.class.getClassLoader(), "view.jar");
+    return new ViewEntity(viewConfig, ambariConfig, ViewEntityTest.class.getClassLoader(), "view.jar");
   }
 
   @Test
   public void testGetName() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
     Assert.assertEquals("MY_VIEW", viewDefinition.getName());
   }
 
   @Test
   public void testGetLabel() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
     Assert.assertEquals("My View!", viewDefinition.getLabel());
   }
 
   @Test
   public void testGetVersion() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
     Assert.assertEquals("1.0.0", viewDefinition.getVersion());
   }
 
   @Test
   public void testGetConfiguration() throws Exception {
     ViewConfig viewConfig = ViewConfigTest.getConfig();
-    ViewDefinition viewDefinition = getViewDefinition(viewConfig);
+    ViewEntity viewDefinition = getViewEntity(viewConfig);
     Assert.assertEquals(viewConfig, viewDefinition.getConfiguration());
   }
 
   @Test
   public void testGetAmbariProperty() throws Exception {
     ViewConfig viewConfig = ViewConfigTest.getConfig();
-    ViewDefinition viewDefinition = getViewDefinition(viewConfig);
+    ViewEntity viewDefinition = getViewEntity(viewConfig);
     Assert.assertEquals("v1", viewDefinition.getAmbariProperty("p1"));
     Assert.assertEquals("v2", viewDefinition.getAmbariProperty("p2"));
     Assert.assertEquals("v3", viewDefinition.getAmbariProperty("p3"));
@@ -92,7 +94,7 @@ public class ViewDefinitionTest {
 
   @Test
   public void testAddGetResourceProvider() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
 
     ResourceProvider provider1 = createNiceMock(ResourceProvider.class);
 
@@ -118,7 +120,7 @@ public class ViewDefinitionTest {
 
   @Test
   public void testAddGetResourceDefinition() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
 
     ViewSubResourceDefinition definition = createNiceMock(ViewSubResourceDefinition.class);
     Resource.Type type = new Resource.Type("myType");
@@ -136,7 +138,7 @@ public class ViewDefinitionTest {
 
   @Test
   public void testAddGetResourceConfiguration() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
 
     ResourceConfig config = ResourceConfigTest.getResourceConfigs().get(0);
 
@@ -155,11 +157,11 @@ public class ViewDefinitionTest {
 
   @Test
   public void testAddGetInstanceDefinition() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
+    ViewEntity viewDefinition = getViewEntity();
 
-    ViewInstanceDefinition definition = createNiceMock(ViewInstanceDefinition.class);
+    ViewInstanceEntity definition = createNiceMock(ViewInstanceEntity.class);
 
-    expect(definition.getName()).andReturn("instance1");
+    expect(definition.getName()).andReturn("instance1").anyTimes();
 
     replay(definition);
 
@@ -167,7 +169,7 @@ public class ViewDefinitionTest {
 
     Assert.assertEquals(definition, viewDefinition.getInstanceDefinition("instance1"));
 
-    Collection<ViewInstanceDefinition> definitions = viewDefinition.getInstanceDefinitions();
+    Collection<ViewInstanceEntity> definitions = viewDefinition.getInstances();
 
     Assert.assertEquals(1, definitions.size());
 
@@ -178,13 +180,13 @@ public class ViewDefinitionTest {
 
   @Test
   public void testGetClassLoader() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
-    Assert.assertEquals(ViewDefinitionTest.class.getClassLoader(), viewDefinition.getClassLoader());
+    ViewEntity viewDefinition = getViewEntity();
+    Assert.assertEquals(ViewEntityTest.class.getClassLoader(), viewDefinition.getClassLoader());
   }
 
   @Test
-  public void testGetArchivePath() throws Exception {
-    ViewDefinition viewDefinition = getViewDefinition();
-    Assert.assertEquals("view.jar", viewDefinition.getArchivePath());
+  public void testGetArchive() throws Exception {
+    ViewEntity viewDefinition = getViewEntity();
+    Assert.assertEquals("view.jar", viewDefinition.getArchive());
   }
 }

+ 23 - 22
ambari-server/src/test/java/org/apache/ambari/server/view/ViewInstanceDefinitionTest.java → ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java

@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package org.apache.ambari.server.view;
+package org.apache.ambari.server.orm.entities;
 
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
@@ -30,43 +30,44 @@ import java.util.Map;
 import static org.easymock.EasyMock.createNiceMock;
 
 /**
- * ViewInstanceDefinition tests.
+ * ViewInstanceEntity tests.
  */
-public class ViewInstanceDefinitionTest {
+public class ViewInstanceEntityTest {
+
   @Test
-  public void testGetViewDefinition() throws Exception {
+  public void testGetViewEntity() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
 
-    Assert.assertEquals(viewDefinition, viewInstanceDefinition.getViewDefinition());
+    Assert.assertEquals(viewDefinition, viewInstanceDefinition.getViewEntity());
   }
 
   @Test
   public void testGetConfiguration() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
 
     Assert.assertEquals(instanceConfig, viewInstanceDefinition.getConfiguration());
   }
 
   @Test
   public void testGetName() throws Exception {
-    ViewInstanceDefinition viewInstanceDefinition = getViewInstanceDefinition();
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
     Assert.assertEquals("INSTANCE1", viewInstanceDefinition.getName());
   }
 
   @Test
   public void testAddGetProperty() throws Exception {
-    ViewInstanceDefinition viewInstanceDefinition = getViewInstanceDefinition();
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
-    viewInstanceDefinition.addProperty("p1", "v1");
-    viewInstanceDefinition.addProperty("p2", "v2");
-    viewInstanceDefinition.addProperty("p3", "v3");
+    viewInstanceDefinition.putProperty("p1", "v1");
+    viewInstanceDefinition.putProperty("p2", "v2");
+    viewInstanceDefinition.putProperty("p3", "v3");
 
-    Map<String, String> properties = viewInstanceDefinition.getProperties();
+    Map<String, String> properties = viewInstanceDefinition.getPropertyMap();
 
     Assert.assertEquals(3, properties.size());
 
@@ -77,7 +78,7 @@ public class ViewInstanceDefinitionTest {
 
   @Test
   public void testAddGetService() throws Exception {
-    ViewInstanceDefinition viewInstanceDefinition = getViewInstanceDefinition();
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
     Object service = new Object();
 
@@ -93,7 +94,7 @@ public class ViewInstanceDefinitionTest {
 
   @Test
   public void testAddGetResourceProvider() throws Exception {
-    ViewInstanceDefinition viewInstanceDefinition = getViewInstanceDefinition();
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
     ResourceProvider provider = createNiceMock(ResourceProvider.class);
     Resource.Type type = new Resource.Type("MY_VIEW/myType");
@@ -106,15 +107,15 @@ public class ViewInstanceDefinitionTest {
 
   @Test
   public void testContextPath() throws Exception {
-    ViewInstanceDefinition viewInstanceDefinition = getViewInstanceDefinition();
+    ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
-    Assert.assertEquals(ViewInstanceDefinition.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/INSTANCE1",
+    Assert.assertEquals(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/INSTANCE1",
         viewInstanceDefinition.getContextPath());
   }
 
-  public static ViewInstanceDefinition getViewInstanceDefinition() throws Exception {
+  public static ViewInstanceEntity getViewInstanceEntity() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    return new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    return new ViewInstanceEntity(viewDefinition, instanceConfig);
   }
 }

+ 26 - 18
ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java

@@ -20,6 +20,9 @@ package org.apache.ambari.server.view;
 
 import org.apache.ambari.server.controller.internal.URLStreamProvider;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityTest;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfigTest;
 import org.apache.ambari.view.ResourceProvider;
@@ -45,10 +48,11 @@ public class ViewContextImplTest {
   @Test
   public void testGetViewName() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
 
-    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition);
+    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry);
 
     Assert.assertEquals("MY_VIEW", viewContext.getViewName());
   }
@@ -56,10 +60,11 @@ public class ViewContextImplTest {
   @Test
   public void testGetInstanceName() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
 
-    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition);
+    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry);
 
     Assert.assertEquals("INSTANCE1", viewContext.getInstanceName());
   }
@@ -67,13 +72,14 @@ public class ViewContextImplTest {
   @Test
   public void testGetProperties() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
-    viewInstanceDefinition.addProperty("p1", "v1");
-    viewInstanceDefinition.addProperty("p2", "v2");
-    viewInstanceDefinition.addProperty("p3", "v3");
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+    viewInstanceDefinition.putProperty("p1", "v1");
+    viewInstanceDefinition.putProperty("p2", "v2");
+    viewInstanceDefinition.putProperty("p3", "v3");
 
-    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition);
+    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry);
 
     Map<String, String> properties = viewContext.getProperties();
     Assert.assertEquals(3, properties.size());
@@ -86,15 +92,16 @@ public class ViewContextImplTest {
   @Test
   public void testGetResourceProvider() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
 
     ResourceProvider provider = createNiceMock(ResourceProvider.class);
     Resource.Type type = new Resource.Type("MY_VIEW/myType");
 
     viewInstanceDefinition.addResourceProvider(type, provider);
 
-    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition);
+    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry);
 
     Assert.assertEquals(provider, viewContext.getResourceProvider("myType"));
   }
@@ -102,15 +109,16 @@ public class ViewContextImplTest {
   @Test
   public void testGetURLStreamProvider() throws Exception {
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = new ViewInstanceDefinition(viewDefinition, instanceConfig);
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);
+    ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
 
     ResourceProvider provider = createNiceMock(ResourceProvider.class);
     Resource.Type type = new Resource.Type("MY_VIEW/myType");
 
     viewInstanceDefinition.addResourceProvider(type, provider);
 
-    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition);
+    ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry);
 
     Assert.assertNotNull(viewContext.getURLStreamProvider());
   }

+ 18 - 13
ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java

@@ -21,12 +21,14 @@ package org.apache.ambari.server.view;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityTest;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntityTest;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfigTest;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
 import org.apache.ambari.server.view.configuration.ResourceConfigTest;
-import org.apache.ambari.server.view.configuration.ViewConfig;
-import org.apache.ambari.server.view.configuration.ViewConfigTest;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
@@ -43,7 +45,7 @@ import static org.easymock.EasyMock.createNiceMock;
 public class ViewRegistryTest {
   @Test
   public void testAddGetDefinitions() throws Exception {
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -51,7 +53,7 @@ public class ViewRegistryTest {
 
     Assert.assertEquals(viewDefinition, registry.getDefinition("MY_VIEW"));
 
-    Collection<ViewDefinition> viewDefinitions = registry.getDefinitions();
+    Collection<ViewEntity> viewDefinitions = registry.getDefinitions();
 
     Assert.assertEquals(1, viewDefinitions.size());
 
@@ -60,8 +62,8 @@ public class ViewRegistryTest {
 
   @Test
   public void testAddGetInstanceDefinitions() throws Exception {
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
-    ViewInstanceDefinition viewInstanceDefinition = ViewInstanceDefinitionTest.getViewInstanceDefinition();
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    ViewInstanceEntity viewInstanceDefinition = ViewInstanceEntityTest.getViewInstanceEntity();
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -71,7 +73,7 @@ public class ViewRegistryTest {
 
     Assert.assertEquals(viewInstanceDefinition, registry.getInstanceDefinition("MY_VIEW", "INSTANCE1"));
 
-    Collection<ViewInstanceDefinition> viewInstanceDefinitions = registry.getInstanceDefinitions(viewDefinition);
+    Collection<ViewInstanceEntity> viewInstanceDefinitions = registry.getInstanceDefinitions(viewDefinition);
 
     Assert.assertEquals(1, viewInstanceDefinitions.size());
 
@@ -80,7 +82,7 @@ public class ViewRegistryTest {
 
   @Test
   public void testGetSubResourceDefinitions() throws Exception {
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
     ViewRegistry registry = ViewRegistry.getInstance();
 
     ResourceConfig config = ResourceConfigTest.getResourceConfigs().get(0);
@@ -98,19 +100,22 @@ public class ViewRegistryTest {
   }
 
   @Test
-  public void testInstallViewInstance() throws Exception {
+  public void testAddInstanceDefinition() throws Exception {
     ViewRegistry registry = ViewRegistry.getInstance();
 
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
+    ViewEntity viewEntity = ViewEntityTest.getViewEntity();
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
 
-    ViewInstanceDefinition viewInstanceDefinition = ViewRegistry.installViewInstance(viewDefinition, instanceConfig);
+    ViewInstanceEntity viewInstanceEntity = new ViewInstanceEntity(viewEntity, instanceConfig);
 
-    Collection<ViewInstanceDefinition> viewInstanceDefinitions = registry.getInstanceDefinitions(viewDefinition);
+    registry.addDefinition(viewEntity);
+    registry.addInstanceDefinition(viewEntity, viewInstanceEntity);
+
+    Collection<ViewInstanceEntity> viewInstanceDefinitions = registry.getInstanceDefinitions(viewEntity);
 
     Assert.assertEquals(1, viewInstanceDefinitions.size());
 
-    Assert.assertEquals(viewInstanceDefinition, viewInstanceDefinitions.iterator().next());
+    Assert.assertEquals(viewInstanceEntity, viewInstanceDefinitions.iterator().next());
   }
 
   @Before

+ 3 - 1
ambari-server/src/test/java/org/apache/ambari/server/view/ViewSubResourceDefinitionTest.java

@@ -20,6 +20,8 @@ package org.apache.ambari.server.view;
 
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityTest;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
 import org.apache.ambari.server.view.configuration.ResourceConfigTest;
 import org.junit.Assert;
@@ -60,7 +62,7 @@ public class ViewSubResourceDefinitionTest {
   }
 
   public static ViewSubResourceDefinition getViewSubResourceDefinition() throws Exception {
-    ViewDefinition viewDefinition = ViewDefinitionTest.getViewDefinition();
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
     ResourceConfig resourceConfig = ResourceConfigTest.getResourceConfigs().get(0);
 
     return new ViewSubResourceDefinition(viewDefinition, resourceConfig);

+ 31 - 0
ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java

@@ -60,6 +60,37 @@ public interface ViewContext {
    */
   public Map<String, String> getProperties();
 
+  /**
+   * Save an instance data value for the given key.
+   *
+   * @param key    the key
+   * @param value  the value
+   */
+  public void putInstanceData(String key, String value);
+
+  /**
+   * Get the instance data value for the given key.
+   *
+   * @param key  the key
+   *
+   * @return the instance data value
+   */
+  public String getInstanceData(String key);
+
+  /**
+   * Get the instance data values.
+   *
+   * @return the view instance property values
+   */
+  public Map<String, String> getInstanceData();
+
+  /**
+   * Remove the instance data value for the given key.
+   *
+   * @param key  the key
+   */
+  public void removeInstanceData(String key);
+
   /**
    * Get a property for the given key from the ambari configuration.
    *