org.apache.ambari.server.view.ViewRegistry.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.server.view.ViewRegistry.java

Source

/**
 * 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 com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.persist.Transactional;
import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
import org.apache.ambari.server.api.resources.SubResourceDefinition;
import org.apache.ambari.server.api.resources.ViewExternalSubResourceDefinition;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.api.services.ViewExternalSubResourceService;
import org.apache.ambari.server.api.services.ViewSubResourceService;
import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.AmbariServer;
import org.apache.ambari.server.controller.AmbariSessionManager;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.ResourceProvider;
import org.apache.ambari.server.orm.dao.MemberDAO;
import org.apache.ambari.server.orm.dao.PrivilegeDAO;
import org.apache.ambari.server.orm.dao.ResourceDAO;
import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
import org.apache.ambari.server.orm.dao.UserDAO;
import org.apache.ambari.server.orm.dao.ViewDAO;
import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
import org.apache.ambari.server.orm.entities.GroupEntity;
import org.apache.ambari.server.orm.entities.MemberEntity;
import org.apache.ambari.server.orm.entities.PermissionEntity;
import org.apache.ambari.server.orm.entities.PrincipalEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
import org.apache.ambari.server.orm.entities.ResourceEntity;
import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
import org.apache.ambari.server.orm.entities.UserEntity;
import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.orm.entities.ViewEntityEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
import org.apache.ambari.server.orm.entities.ViewParameterEntity;
import org.apache.ambari.server.orm.entities.ViewResourceEntity;
import org.apache.ambari.server.security.SecurityHelper;
import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
import org.apache.ambari.server.utils.VersionUtils;
import org.apache.ambari.server.view.configuration.EntityConfig;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.server.view.configuration.ParameterConfig;
import org.apache.ambari.server.view.configuration.PermissionConfig;
import org.apache.ambari.server.view.configuration.PersistenceConfig;
import org.apache.ambari.server.view.configuration.PropertyConfig;
import org.apache.ambari.server.view.configuration.ResourceConfig;
import org.apache.ambari.server.view.configuration.ViewConfig;
import org.apache.ambari.server.view.validation.ValidationException;
import org.apache.ambari.view.validation.Validator;
import org.apache.ambari.view.Masker;
import org.apache.ambari.view.SystemException;
import org.apache.ambari.view.View;
import org.apache.ambari.view.ViewContext;
import org.apache.ambari.view.ViewDefinition;
import org.apache.ambari.view.ViewResourceHandler;
import org.apache.ambari.view.events.Event;
import org.apache.ambari.view.events.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.beans.IntrospectionException;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Registry for view and view instance definitions.
 */
@Singleton
public class ViewRegistry {

    /**
     * Constants
     */
    private static final String EXTRACTED_ARCHIVES_DIR = "work";
    private static final String EXTRACT_COMMAND = "extract";
    private static final String ALL_VIEWS_REG_EXP = ".*";
    protected static final int DEFAULT_REQUEST_CONNECT_TIMEOUT = 5000;
    protected static final int DEFAULT_REQUEST_READ_TIMEOUT = 10000;
    private static final String VIEW_AMBARI_VERSION_REGEXP = "^((\\d+\\.)?)*(\\*|\\d+)$";

    /**
     * Thread pool
     */
    private static ExecutorService executorService;

    /**
     * Mapping of view names to view definitions.
     */
    private Map<String, ViewEntity> viewDefinitions = new HashMap<String, ViewEntity>();

    /**
     * Mapping of view instances to view definition and instance name.
     */
    private Map<ViewEntity, Map<String, ViewInstanceEntity>> viewInstanceDefinitions = new HashMap<ViewEntity, Map<String, ViewInstanceEntity>>();

    /**
     * Mapping of view names to sub-resources.
     */
    private final Map<String, Set<SubResourceDefinition>> subResourceDefinitionsMap = new ConcurrentHashMap<String, Set<SubResourceDefinition>>();

    /**
     * Mapping of view types to resource providers.
     */
    private final Map<Resource.Type, ResourceProvider> resourceProviders = new ConcurrentHashMap<Resource.Type, ResourceProvider>();

    /**
     * Mapping of view names to registered listeners.
     */
    private final Map<String, Set<Listener>> listeners = new ConcurrentHashMap<String, Set<Listener>>();

    /**
     * The singleton view registry instance.
     */
    private static ViewRegistry singleton;

    /**
     * The logger.
     */
    protected final static Logger LOG = LoggerFactory.getLogger(ViewRegistry.class);

    /**
     * View data access object.
     */
    @Inject
    ViewDAO viewDAO;

    /**
     * View instance data access object.
     */
    @Inject
    ViewInstanceDAO instanceDAO;

    /**
     * User data access object.
     */
    @Inject
    UserDAO userDAO;

    /**
     * Group member data access object.
     */
    @Inject
    MemberDAO memberDAO;

    /**
     * Privilege data access object.
     */
    @Inject
    PrivilegeDAO privilegeDAO;

    /**
     * Helper with security related utilities.
     */
    @Inject
    SecurityHelper securityHelper;

    /**
     * Resource data access object.
     */
    @Inject
    ResourceDAO resourceDAO;

    /**
     * Resource type data access object.
     */
    @Inject
    ResourceTypeDAO resourceTypeDAO;

    /**
     * Ambari meta info.
     */
    @Inject
    Provider<AmbariMetaInfo> ambariMetaInfo;

    /**
     * Ambari configuration.
     */
    @Inject
    Configuration configuration;

    /**
     * The handler list.
     */
    @Inject
    ViewInstanceHandlerList handlerList;

    /**
     * The view extractor;
     */
    @Inject
    ViewExtractor extractor;

    /**
     * The view archive utility.
     */
    @Inject
    ViewArchiveUtility archiveUtility;

    /**
     * The Ambari session manager.
     */
    @Inject
    AmbariSessionManager ambariSessionManager;

    // ----- ViewRegistry ------------------------------------------------------

    /**
     * Registry main method.
     *
     * @param args  the command line arguments
     */
    public static void main(String[] args) {

        if (args.length >= 2) {
            String archivePath = args[1];

            try {
                Injector injector = Guice.createInjector();

                ViewExtractor extractor = injector.getInstance(ViewExtractor.class);
                ViewArchiveUtility archiveUtility = injector.getInstance(ViewArchiveUtility.class);
                Configuration configuration = injector.getInstance(Configuration.class);

                if (args[0].equals(EXTRACT_COMMAND)) {
                    if (extractViewArchive(archivePath, extractor, archiveUtility, configuration, true)) {
                        System.exit(0);
                    }
                }
            } catch (Exception e) {
                String msg = "Caught exception extracting view archive " + archivePath + ".";
                LOG.error(msg, e);
                System.exit(2);
            }
        }
        System.exit(1);
    }

    /**
     * Get the collection of all the view definitions.
     *
     * @return the collection of view definitions
     */
    public Collection<ViewEntity> getDefinitions() {
        return viewDefinitions.values();
    }

    /**
     * Get a view definition for the given name.
     *
     * @param viewName  the view name
     * @param version   the version
     *
     * @return the view definition for the given name
     */
    public ViewEntity getDefinition(String viewName, String version) {
        return getDefinition(ViewEntity.getViewName(viewName, version));
    }

    /**
     * Get the view definition for the given resource type.
     *
     * @param resourceTypeEntity  the resource type
     *
     * @return the view definition for the given resource type or null
     */
    public ViewEntity getDefinition(ResourceTypeEntity resourceTypeEntity) {

        for (ViewEntity viewEntity : viewDefinitions.values()) {
            if (viewEntity.isDeployed()) {
                if (viewEntity.getResourceType().equals(resourceTypeEntity)) {
                    return viewEntity;
                }
            }
        }
        return null;
    }

    /**
     * Add a view definition to the registry.
     *
     * @param definition  the definition
     */
    public void addDefinition(ViewEntity definition) {
        viewDefinitions.put(definition.getName(), definition);
    }

    /**
     * Get the collection of view instances for the given view definition.
     *
     * @param definition  the view definition
     *
     * @return the collection of view instances for the view definition
     */
    public Collection<ViewInstanceEntity> getInstanceDefinitions(ViewEntity definition) {
        if (definition != null) {
            Map<String, ViewInstanceEntity> instanceEntityMap = viewInstanceDefinitions.get(definition);
            if (instanceEntityMap != null) {
                return instanceEntityMap.values();
            }
        }
        return Collections.emptyList();
    }

    /**
     * Get the instance definition for the given view name and instance name.
     *
     * @param viewName      the view name
     * @param version       the version
     * @param instanceName  the instance name
     *
     * @return the view instance definition for the given view and instance name
     */
    public ViewInstanceEntity getInstanceDefinition(String viewName, String version, String instanceName) {
        Map<String, ViewInstanceEntity> viewInstanceDefinitionMap = viewInstanceDefinitions
                .get(getDefinition(viewName, version));

        return viewInstanceDefinitionMap == null ? null : viewInstanceDefinitionMap.get(instanceName);
    }

    /**
     * Add an instance definition for the given view definition.
     *
     * @param definition          the owning view definition
     * @param instanceDefinition  the instance definition
     */
    public void addInstanceDefinition(ViewEntity definition, ViewInstanceEntity instanceDefinition) {
        Map<String, ViewInstanceEntity> instanceDefinitions = viewInstanceDefinitions.get(definition);
        if (instanceDefinitions == null) {
            instanceDefinitions = new HashMap<String, ViewInstanceEntity>();
            viewInstanceDefinitions.put(definition, instanceDefinitions);
        }

        View view = definition.getView();
        if (view != null) {
            view.onCreate(instanceDefinition);
        }
        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) {

            ViewInstanceEntity instanceDefinition = instanceDefinitions.get(instanceName);
            if (instanceDefinition != null) {
                View view = definition.getView();
                if (view != null) {
                    view.onDestroy(instanceDefinition);
                }
                instanceDefinitions.remove(instanceName);
            }
        }
    }

    /**
     * Init the singleton instance.
     *
     * @param singleton  the view registry
     */
    public static void initInstance(ViewRegistry singleton) {
        ViewRegistry.singleton = singleton;
    }

    /**
     * Get the view registry singleton.
     *
     * @return  the view registry
     */
    public static ViewRegistry getInstance() {
        return singleton;
    }

    /**
     * Get the sub-resource definitions for the given view name.
     *
     * @param viewName  the instance name
     * @param version   the version
     *
     * @return the set of sub-resource definitions
     */
    public Set<SubResourceDefinition> getSubResourceDefinitions(String viewName, String version) {

        viewName = ViewEntity.getViewName(viewName, version);

        return subResourceDefinitionsMap.get(viewName);
    }

    /**
     * Read all view archives.
     */
    public void readViewArchives() {
        readViewArchives(false, true, ALL_VIEWS_REG_EXP, true);
    }

    /**
     * Read only view archives with names corresponding to given regular expression.
     *
     * @param viewNameRegExp view name regular expression
     */
    public void readViewArchives(String viewNameRegExp) {
        readViewArchives(false, false, viewNameRegExp, false);
    }

    /**
     * Determine whether or not the given view instance exists.
     *
     * @param instanceEntity  the view instance entity
     *
     * @return true if the the given view instance exists; false otherwise
     */
    public boolean instanceExists(ViewInstanceEntity instanceEntity) {

        ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());

        return viewEntity != null && (getInstanceDefinition(viewEntity.getCommonName(), viewEntity.getVersion(),
                instanceEntity.getName()) != null);
    }

    /**
     * Install the given view instance with its associated view.
     *
     * @param instanceEntity  the view instance entity
     *
     * @throws ValidationException       if the given instance fails the validation checks
     * @throws IllegalArgumentException  if the view associated with the given instance
     *                                   does not exist
     * @throws SystemException           if the instance can not be installed
     */
    @Transactional
    public void installViewInstance(ViewInstanceEntity instanceEntity)
            throws ValidationException, IllegalArgumentException, SystemException {
        ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());

        if (viewEntity != null) {
            String instanceName = instanceEntity.getName();
            String viewName = viewEntity.getCommonName();
            String version = viewEntity.getVersion();

            if (getInstanceDefinition(viewName, version, instanceName) == null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Creating view instance " + viewName + "/" + version + "/" + instanceName);
                }

                instanceEntity.validate(viewEntity, Validator.ValidationContext.PRE_CREATE);

                ResourceTypeEntity resourceTypeEntity = resourceTypeDAO
                        .findByName(ViewEntity.getViewName(viewName, version));
                // create an admin resource to represent this view instance
                instanceEntity.setResource(createViewInstanceResource(resourceTypeEntity));

                instanceDAO.merge(instanceEntity);

                ViewInstanceEntity persistedInstance = instanceDAO
                        .findByName(ViewEntity.getViewName(viewName, version), instanceName);
                if (persistedInstance == null) {
                    String message = "Instance  " + instanceEntity.getViewName() + " can not be found.";

                    LOG.error(message);
                    throw new IllegalStateException(message);
                }
                instanceEntity.setViewInstanceId(persistedInstance.getViewInstanceId());
                instanceEntity.setResource(persistedInstance.getResource());

                try {
                    // bind the view instance to a view
                    bindViewInstance(viewEntity, instanceEntity);
                } catch (Exception e) {
                    String message = "Caught exception installing view instance.";
                    LOG.error(message, e);
                    throw new IllegalStateException(message, e);
                }
                // update the registry
                addInstanceDefinition(viewEntity, instanceEntity);

                // add the web app context
                handlerList.addViewInstance(instanceEntity);
            }
        } else {
            String message = "Attempt to install an instance for an unknown view " + instanceEntity.getViewName()
                    + ".";

            LOG.error(message);
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Update a view instance for the view with the given view name.
     *
     * @param instanceEntity  the view instance entity
     *
     * @throws ValidationException   if the given instance fails the validation checks
     * @throws SystemException       if the instance can not be updated
     */
    public void updateViewInstance(ViewInstanceEntity instanceEntity) throws ValidationException, SystemException {
        ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());

        if (viewEntity != null) {
            instanceEntity.validate(viewEntity, Validator.ValidationContext.PRE_UPDATE);
            instanceDAO.merge(instanceEntity);

            syncViewInstance(instanceEntity);
        }
    }

    /**
     * Get a view instance entity for the given view name and instance name.
     *
     * @param viewName      the view name
     * @param instanceName  the instance name
     *
     * @return a view instance entity for the given view name and instance name.
     */
    public ViewInstanceEntity getViewInstanceEntity(String viewName, String instanceName) {
        return instanceDAO.findByName(viewName, instanceName);
    }

    /**
     * Uninstall a view instance for the view with the given view name.
     *
     * @param instanceEntity  the view instance entity
     * @throws IllegalStateException if the given instance is not in a valid state
     */
    @Transactional
    public void uninstallViewInstance(ViewInstanceEntity instanceEntity) throws IllegalStateException {
        ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());

        if (viewEntity != null) {
            String instanceName = instanceEntity.getName();
            String viewName = viewEntity.getCommonName();
            String version = viewEntity.getVersion();

            if (getInstanceDefinition(viewName, version, instanceName) != null) {
                if (instanceEntity.isXmlDriven()) {
                    throw new IllegalStateException(
                            "View instances defined via xml can't be deleted through api requests");
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Deleting view instance " + viewName + "/" + version + "/" + instanceName);
                }
                List<PrivilegeEntity> instancePrivileges = privilegeDAO
                        .findByResourceId(instanceEntity.getResource().getId());
                for (PrivilegeEntity privilegeEntity : instancePrivileges) {
                    removePrivilegeEntity(privilegeEntity);
                }
                instanceDAO.remove(instanceEntity);
                viewEntity.removeInstanceDefinition(instanceName);
                removeInstanceDefinition(viewEntity, instanceName);

                // remove the web app context
                handlerList.removeViewInstance(instanceEntity);
            }
        }
    }

    /**
     * Remove the data entry keyed by the given key from the given instance entity.
     *
     * @param instanceEntity  the instance entity
     * @param key             the data key
     */
    @Transactional
    public void removeInstanceData(ViewInstanceEntity instanceEntity, String key) {
        ViewInstanceDataEntity dataEntity = instanceEntity.getInstanceData(key);
        if (dataEntity != null) {
            instanceDAO.removeData(dataEntity);
        }
        instanceEntity.removeInstanceData(key);
        instanceDAO.merge(instanceEntity);
    }

    /**
     * Notify any registered listeners of the given event.
     *
     * @param event  the event
     */
    public void fireEvent(Event event) {

        ViewDefinition subject = event.getViewSubject();

        fireEvent(event, subject.getViewName());
        fireEvent(event, ViewEntity.getViewName(subject.getViewName(), subject.getVersion()));
    }

    /**
     * Register the given listener to listen for events from the view identified by the given name and version.
     *
     * @param listener     the listener
     * @param viewName     the view name
     * @param viewVersion  the view version; null indicates all versions
     */
    public synchronized void registerListener(Listener listener, String viewName, String viewVersion) {

        String name = viewVersion == null ? viewName : ViewEntity.getViewName(viewName, viewVersion);

        Set<Listener> listeners = this.listeners.get(name);

        if (listeners == null) {
            listeners = Sets.newSetFromMap(new ConcurrentHashMap<Listener, Boolean>());
            this.listeners.put(name, listeners);
        }

        listeners.add(listener);
    }

    /**
     * Un-register the given listener from the view identified by the given name and version.
     *
     * @param listener     the listener
     * @param viewName     the view name
     * @param viewVersion  the view version; null indicates all versions
     */
    public synchronized void unregisterListener(Listener listener, String viewName, String viewVersion) {

        String name = viewVersion == null ? viewName : ViewEntity.getViewName(viewName, viewVersion);

        Set<Listener> listeners = this.listeners.get(name);

        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    /**
     * Determine whether or not the access specified by the given permission
     * is permitted for the given user on the view instance identified by
     * the given resource.
     *
     * @param permissionEntity  the permission entity
     * @param resourceEntity    the resource entity
     * @param userName          the user name
     *
     * @return true if the access specified by the given permission
     *         is permitted for the given user.
     */
    public boolean hasPermission(PermissionEntity permissionEntity, ResourceEntity resourceEntity,
            String userName) {

        UserEntity userEntity = userDAO.findUserByName(userName);

        if (userEntity == null) {
            return false;
        }

        if (privilegeDAO.exists(userEntity.getPrincipal(), resourceEntity, permissionEntity)) {
            return true;
        }

        List<MemberEntity> memberEntities = memberDAO.findAllMembersByUser(userEntity);

        for (MemberEntity memberEntity : memberEntities) {

            GroupEntity groupEntity = memberEntity.getGroup();

            if (privilegeDAO.exists(groupEntity.getPrincipal(), resourceEntity, permissionEntity)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Determine whether or not access to the view instance resource identified
     * by the given instance name should be allowed based on the permissions
     * granted to the current user.
     *
     * @param viewName      the view name
     * @param version       the view version
     * @param instanceName  the name of the view instance resource
     * @param readOnly      indicate whether or not this is for a read only operation
     *
     * @return true if the access to the view instance is allowed
     */
    public boolean checkPermission(String viewName, String version, String instanceName, boolean readOnly) {

        ViewInstanceEntity instanceEntity = instanceName == null ? null
                : getInstanceDefinition(viewName, version, instanceName);

        return checkPermission(instanceEntity, readOnly);
    }

    /**
     * Determine whether or not access to the given view instance should be allowed based
     * on the permissions granted to the current user.
     *
     * @param instanceEntity  the view instance entity
     * @param readOnly        indicate whether or not this is for a read only operation
     *
     * @return true if the access to the view instance is allowed
     */
    public boolean checkPermission(ViewInstanceEntity instanceEntity, boolean readOnly) {

        ResourceEntity resourceEntity = instanceEntity == null ? null : instanceEntity.getResource();

        return !configuration.getApiAuthentication() || (resourceEntity == null && readOnly)
                || checkAuthorization(resourceEntity);
    }

    /**
     * Determine whether or not the current view user has admin rights.
     *
     * @return true if the current view user is an admin
     */
    public boolean checkAdmin() {
        return checkAuthorization(null);
    }

    /**
     * Determine whether or not the given view definition resource should be included
     * based on the permissions granted to the current user.
     *
     * @param definitionEntity  the view definition entity
     *
     * @return true if the view instance should be included based on the permissions of the current user
     */
    public boolean includeDefinition(ViewEntity definitionEntity) {

        if (checkPermission(null, false)) {
            return true;
        }

        for (ViewInstanceEntity instanceEntity : definitionEntity.getInstances()) {
            if (checkPermission(instanceEntity, true)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Set the properties of the given view instance from the given property set.
     *
     * @param instanceEntity  the view instance entity
     * @param properties      the view instance properties
     * @param viewConfig      the view configuration
     * @param classLoader     the class loader for the view
     *
     * @throws SystemException if the view instance properties can not be set
     */
    public void setViewInstanceProperties(ViewInstanceEntity instanceEntity, Map<String, String> properties,
            ViewConfig viewConfig, ClassLoader classLoader) throws SystemException {
        try {
            Masker masker = getMasker(viewConfig.getMaskerClass(classLoader));

            Map<String, ParameterConfig> parameterConfigMap = new HashMap<String, ParameterConfig>();
            for (ParameterConfig paramConfig : viewConfig.getParameters()) {
                parameterConfigMap.put(paramConfig.getName(), paramConfig);
            }
            for (Map.Entry<String, String> entry : properties.entrySet()) {
                String name = entry.getKey();
                String value = entry.getValue();

                ParameterConfig parameterConfig = parameterConfigMap.get(name);

                if (parameterConfig != null && parameterConfig.isMasked()) {
                    value = masker.mask(value);
                }
                instanceEntity.putProperty(name, value);
            }
        } catch (Exception e) {
            throw new SystemException("Caught exception while setting instance property.", e);
        }
    }

    // ----- helper methods ----------------------------------------------------

    /**
     * Clear the registry.
     */
    protected void clear() {
        viewDefinitions.clear();
        viewInstanceDefinitions.clear();
        subResourceDefinitionsMap.clear();
        listeners.clear();
    }

    /**
     * Get the view resource provider mapping.
     *
     * @return the map of view resource providers
     */
    protected Map<Resource.Type, ResourceProvider> getResourceProviders() {
        return resourceProviders;
    }

    // get a view entity for the given internal view name
    private ViewEntity getDefinition(String viewName) {
        return viewDefinitions.get(viewName);
    }

    // setup the given view definition
    protected ViewEntity setupViewDefinition(ViewEntity viewDefinition, ClassLoader cl)
            throws ClassNotFoundException, IntrospectionException {

        ViewConfig viewConfig = viewDefinition.getConfiguration();

        viewDefinition.setClassLoader(cl);

        List<ParameterConfig> parameterConfigurations = viewConfig.getParameters();

        Collection<ViewParameterEntity> parameters = new HashSet<ViewParameterEntity>();

        String viewName = viewDefinition.getName();

        for (ParameterConfig parameterConfiguration : parameterConfigurations) {
            ViewParameterEntity viewParameterEntity = new ViewParameterEntity();

            viewParameterEntity.setViewName(viewName);
            viewParameterEntity.setName(parameterConfiguration.getName());
            viewParameterEntity.setDescription(parameterConfiguration.getDescription());
            viewParameterEntity.setLabel(parameterConfiguration.getLabel());
            viewParameterEntity.setPlaceholder(parameterConfiguration.getPlaceholder());
            viewParameterEntity.setDefaultValue(parameterConfiguration.getDefaultValue());
            viewParameterEntity.setRequired(parameterConfiguration.isRequired());
            viewParameterEntity.setMasked(parameterConfiguration.isMasked());
            viewParameterEntity.setViewEntity(viewDefinition);
            parameters.add(viewParameterEntity);
        }
        viewDefinition.setParameters(parameters);

        List<ResourceConfig> resourceConfigurations = viewConfig.getResources();

        Resource.Type externalResourceType = viewDefinition.getExternalResourceType();

        ViewExternalSubResourceProvider viewExternalSubResourceProvider = new ViewExternalSubResourceProvider(
                externalResourceType, viewDefinition);
        viewDefinition.addResourceProvider(externalResourceType, viewExternalSubResourceProvider);

        resourceProviders.put(externalResourceType, viewExternalSubResourceProvider);

        ResourceInstanceFactoryImpl.addResourceDefinition(externalResourceType,
                new ViewExternalSubResourceDefinition(externalResourceType));

        Collection<ViewResourceEntity> resources = new HashSet<ViewResourceEntity>();
        for (ResourceConfig resourceConfiguration : resourceConfigurations) {
            ViewResourceEntity viewResourceEntity = new ViewResourceEntity();

            viewResourceEntity.setViewName(viewName);
            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);

            Resource.Type type = resourceDefinition.getType();
            viewDefinition.addResourceConfiguration(type, resourceConfiguration);

            if (resourceConfiguration.isExternal()) {
                viewExternalSubResourceProvider.addResourceName(resourceConfiguration.getName());
            } else {
                ResourceInstanceFactoryImpl.addResourceDefinition(type, resourceDefinition);

                Class<?> clazz = resourceConfiguration.getResourceClass(cl);
                String idProperty = resourceConfiguration.getIdProperty();

                ViewSubResourceProvider provider = new ViewSubResourceProvider(type, clazz, idProperty,
                        viewDefinition);
                viewDefinition.addResourceProvider(type, provider);
                resourceProviders.put(type, provider);

                resources.add(viewResourceEntity);
            }
            viewDefinition.setResources(resources);
        }

        ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
        resourceTypeEntity.setName(viewName);

        viewDefinition.setResourceType(resourceTypeEntity);

        List<PermissionConfig> permissionConfigurations = viewConfig.getPermissions();

        Collection<PermissionEntity> permissions = new HashSet<PermissionEntity>();
        for (PermissionConfig permissionConfiguration : permissionConfigurations) {
            PermissionEntity permissionEntity = new PermissionEntity();

            permissionEntity.setPermissionName(permissionConfiguration.getName());
            permissionEntity.setResourceType(resourceTypeEntity);
            permissions.add(permissionEntity);
        }
        viewDefinition.setPermissions(permissions);

        View view = null;
        if (viewConfig.getView() != null) {
            view = getView(viewConfig.getViewClass(cl), new ViewContextImpl(viewDefinition, this));
        }
        viewDefinition.setView(view);
        Validator validator = null;
        if (viewConfig.getValidator() != null) {
            validator = getValidator(viewConfig.getValidatorClass(cl), new ViewContextImpl(viewDefinition, this));
        }
        viewDefinition.setValidator(validator);
        viewDefinition.setMask(viewConfig.getMasker());

        Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
        for (Resource.Type type : viewDefinition.getViewResourceTypes()) {
            subResourceDefinitions.add(new SubResourceDefinition(type));
        }
        subResourceDefinitionsMap.put(viewName, subResourceDefinitions);

        return viewDefinition;
    }

    // create a new view instance definition
    protected ViewInstanceEntity createViewInstanceDefinition(ViewConfig viewConfig, ViewEntity viewDefinition,
            InstanceConfig instanceConfig) throws ValidationException, ClassNotFoundException, SystemException {
        ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig);

        Map<String, String> properties = new HashMap<String, String>();

        for (PropertyConfig propertyConfig : instanceConfig.getProperties()) {
            properties.put(propertyConfig.getKey(), propertyConfig.getValue());
        }
        setViewInstanceProperties(viewInstanceDefinition, properties, viewConfig, viewDefinition.getClassLoader());
        viewInstanceDefinition.validate(viewDefinition, Validator.ValidationContext.PRE_CREATE);

        bindViewInstance(viewDefinition, viewInstanceDefinition);
        return viewInstanceDefinition;
    }

    // bind a view instance definition to the given view definition
    protected void bindViewInstance(ViewEntity viewDefinition, ViewInstanceEntity viewInstanceDefinition)
            throws ClassNotFoundException {
        viewInstanceDefinition.setViewEntity(viewDefinition);

        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, viewInstanceDefinition);

            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));
            }
        }

        setPersistenceEntities(viewInstanceDefinition);

        viewDefinition.addInstanceDefinition(viewInstanceDefinition);
    }

    // Set the entities defined in the view persistence element for the given view instance
    private static void setPersistenceEntities(ViewInstanceEntity viewInstanceDefinition) {
        ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
        ViewConfig viewConfig = viewDefinition.getConfiguration();

        Collection<ViewEntityEntity> entities = new HashSet<ViewEntityEntity>();

        if (viewConfig != null) {
            PersistenceConfig persistenceConfig = viewConfig.getPersistence();

            if (persistenceConfig != null) {
                for (EntityConfig entityConfiguration : persistenceConfig.getEntities()) {
                    ViewEntityEntity viewEntityEntity = new ViewEntityEntity();

                    viewEntityEntity.setViewName(viewDefinition.getName());
                    viewEntityEntity.setViewInstanceName(viewInstanceDefinition.getName());
                    viewEntityEntity.setClassName(entityConfiguration.getClassName());
                    viewEntityEntity.setIdProperty(entityConfiguration.getIdProperty());
                    viewEntityEntity.setViewInstance(viewInstanceDefinition);

                    entities.add(viewEntityEntity);
                }
            }
        }
        viewInstanceDefinition.setEntities(entities);
    }

    // get the given service class from the given class loader; inject a handler and context
    private static <T> T getService(Class<T> clazz, final ViewResourceHandler viewResourceHandler,
            final ViewContext viewInstanceContext) {
        Injector viewInstanceInjector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ViewResourceHandler.class).toInstance(viewResourceHandler);
                bind(ViewContext.class).toInstance(viewInstanceContext);
            }
        });
        return viewInstanceInjector.getInstance(clazz);
    }

    // get the given resource provider class from the given class loader; inject a context
    private static org.apache.ambari.view.ResourceProvider getProvider(
            Class<? extends org.apache.ambari.view.ResourceProvider> clazz, final ViewContext viewInstanceContext) {
        Injector viewInstanceInjector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ViewContext.class).toInstance(viewInstanceContext);
            }
        });
        return viewInstanceInjector.getInstance(clazz);
    }

    // get the given view class from the given class loader; inject a context
    private static View getView(Class<? extends View> clazz, final ViewContext viewContext) {
        Injector viewInstanceInjector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ViewContext.class).toInstance(viewContext);
            }
        });
        return viewInstanceInjector.getInstance(clazz);
    }

    // get the given view validator class from the given class loader; inject a context
    private static Validator getValidator(Class<? extends Validator> clazz, final ViewContext viewContext) {
        Injector viewInstanceInjector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ViewContext.class).toInstance(viewContext);
            }
        });
        return viewInstanceInjector.getInstance(clazz);
    }

    // create masker from given class; probably replace with injector later
    private static Masker getMasker(Class<? extends Masker> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            LOG.error("Could not create masker instance", e);
        }
        return null;
    }

    // remove undeployed views from the ambari db
    private void removeUndeployedViews() {
        for (ViewEntity viewEntity : viewDAO.findAll()) {
            String name = viewEntity.getName();
            if (!ViewRegistry.getInstance().viewDefinitions.containsKey(name)) {
                try {
                    viewDAO.remove(viewEntity);
                } catch (Exception e) {
                    LOG.error("Caught exception undeploying view " + viewEntity.getName(), e);
                }
            }
        }
    }

    /**
     * Sync given view with data in DB. Ensures that view data in DB is updated,
     * all instances changes from xml config are reflected to DB
     *
     * @param view                 view config from xml
     * @param instanceDefinitions  view instances from xml
     *
     * @throws Exception if the view can not be synced
     */
    private void syncView(ViewEntity view, Set<ViewInstanceEntity> instanceDefinitions) throws Exception {

        String viewName = view.getName();
        ViewEntity persistedView = viewDAO.findByName(viewName);
        ResourceTypeEntity resourceType = view.getResourceType();

        // if the view is not yet persisted ...
        if (persistedView == null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Creating View " + viewName + ".");
            }

            // get or create an admin resource type to represent this view
            ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findByName(viewName);
            if (resourceTypeEntity == null) {
                resourceTypeEntity = resourceType;
                resourceTypeDAO.create(resourceTypeEntity);
            }

            for (ViewInstanceEntity instance : view.getInstances()) {
                instance.setResource(createViewInstanceResource(resourceType));
            }
            // ... merge the view
            persistedView = viewDAO.merge(view);
        }

        view.setResourceType(persistedView.getResourceType());
        view.setPermissions(persistedView.getPermissions());

        // make sure that each instance of the view in the db is reflected in the given view
        for (ViewInstanceEntity persistedInstance : persistedView.getInstances()) {

            String instanceName = persistedInstance.getName();
            ViewInstanceEntity instance = view.getInstanceDefinition(instanceName);

            // if the persisted instance is not in the view ...
            if (instance == null) {
                if (persistedInstance.isXmlDriven()) {
                    // this instance was persisted from an earlier view.xml but has been removed...
                    // remove it from the db
                    instanceDAO.remove(persistedInstance);
                } else {
                    // this instance was not specified in the view.xml but was added through the API...
                    // bind it to the view and add it to the registry
                    instanceDAO.merge(persistedInstance);
                    bindViewInstance(view, persistedInstance);
                    instanceDefinitions.add(persistedInstance);
                }
            } else {
                syncViewInstance(instance, persistedInstance);
            }
        }
    }

    // sync the given view instance entity to the matching view instance entity in the registry
    private void syncViewInstance(ViewInstanceEntity instanceEntity) {
        String viewName = instanceEntity.getViewDefinition().getViewName();
        String version = instanceEntity.getViewDefinition().getVersion();
        String instanceName = instanceEntity.getInstanceName();

        ViewInstanceEntity registryEntry = getInstanceDefinition(viewName, version, instanceName);
        if (registryEntry != null) {
            syncViewInstance(registryEntry, instanceEntity);
        }
    }

    // sync a given view instance entity with another given view instance entity
    private void syncViewInstance(ViewInstanceEntity instance1, ViewInstanceEntity instance2) {
        instance1.setLabel(instance2.getLabel());
        instance1.setDescription(instance2.getDescription());
        instance1.setVisible(instance2.isVisible());
        instance1.setResource(instance2.getResource());
        instance1.setViewInstanceId(instance2.getViewInstanceId());
        instance1.setData(instance2.getData());
        instance1.setEntities(instance2.getEntities());
        instance1.setProperties(instance2.getProperties());
    }

    // create an admin resource to represent a view instance
    private ResourceEntity createViewInstanceResource(ResourceTypeEntity resourceTypeEntity) {
        ResourceEntity resourceEntity = new ResourceEntity();
        resourceEntity.setResourceType(resourceTypeEntity);
        resourceDAO.create(resourceEntity);
        return resourceEntity;
    }

    // notify the view identified by the given view name of the given event
    private void fireEvent(Event event, String viewName) {
        Set<Listener> listeners = this.listeners.get(viewName);

        if (listeners != null) {
            for (Listener listener : listeners) {
                listener.notify(event);
            }
        }
    }

    // check that the current user is authorized to access the given view instance resource
    private boolean checkAuthorization(ResourceEntity resourceEntity) {
        for (GrantedAuthority grantedAuthority : securityHelper.getCurrentAuthorities()) {
            if (grantedAuthority instanceof AmbariGrantedAuthority) {

                AmbariGrantedAuthority authority = (AmbariGrantedAuthority) grantedAuthority;
                PrivilegeEntity privilegeEntity = authority.getPrivilegeEntity();
                Integer permissionId = privilegeEntity.getPermission().getId();

                // admin has full access
                if (permissionId.equals(PermissionEntity.AMBARI_ADMIN_PERMISSION)) {
                    return true;
                }
                if (resourceEntity != null) {
                    // VIEW.USE for the given view instance resource.
                    if (privilegeEntity.getResource().equals(resourceEntity)) {
                        if (permissionId.equals(PermissionEntity.VIEW_USE_PERMISSION)) {
                            return true;
                        }
                    }
                }
            }
        }
        // TODO : should we log this?
        return false;
    }

    // fire the onDeploy event.
    protected void onDeploy(ViewEntity definition) {
        View view = definition.getView();
        if (view != null) {
            view.onDeploy(definition);
        }
    }

    // remove a privilege entity.
    private void removePrivilegeEntity(PrivilegeEntity privilegeEntity) {

        PrincipalEntity principalEntity = privilegeEntity.getPrincipal();
        if (principalEntity != null) {
            principalEntity.removePrivilege(privilegeEntity);
        }

        privilegeDAO.remove(privilegeEntity);
    }

    // read the view archives.
    private void readViewArchives(boolean systemOnly, boolean useExecutor, String viewNameRegExp,
            boolean removeUndeployed) {
        try {
            File viewDir = configuration.getViewsDir();

            String extractedArchivesPath = viewDir.getAbsolutePath() + File.separator + EXTRACTED_ARCHIVES_DIR;

            if (extractor.ensureExtractedArchiveDirectory(extractedArchivesPath)) {

                File[] files = viewDir.listFiles();

                if (files != null) {

                    Set<Runnable> extractionRunnables = new HashSet<Runnable>();

                    final String serverVersion = ambariMetaInfo.get().getServerVersion();

                    for (final File archiveFile : files) {
                        if (!archiveFile.isDirectory()) {

                            try {
                                final ViewConfig viewConfig = archiveUtility.getViewConfigFromArchive(archiveFile);

                                String commonName = viewConfig.getName();
                                String version = viewConfig.getVersion();
                                String viewName = ViewEntity.getViewName(commonName, version);

                                if (!viewName.matches(viewNameRegExp)) {
                                    continue;
                                }

                                final String extractedArchiveDirPath = extractedArchivesPath + File.separator
                                        + viewName;
                                final File extractedArchiveDirFile = archiveUtility
                                        .getFile(extractedArchiveDirPath);

                                final ViewEntity viewDefinition = new ViewEntity(viewConfig, configuration,
                                        extractedArchiveDirPath);

                                boolean systemView = viewDefinition.isSystem();

                                if (!systemOnly || systemView) {
                                    // update the registry with the view
                                    addDefinition(viewDefinition);

                                    // always load system views up front
                                    if (systemView || !useExecutor || extractedArchiveDirFile.exists()) {
                                        // if the archive is already extracted then load the view now
                                        readViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile,
                                                serverVersion);
                                    } else {
                                        // if the archive needs to be extracted then create a runnable to do it
                                        extractionRunnables.add(new Runnable() {
                                            @Override
                                            public void run() {
                                                readViewArchive(viewDefinition, archiveFile,
                                                        extractedArchiveDirFile, serverVersion);
                                            }
                                        });
                                    }
                                }
                            } catch (Exception e) {
                                String msg = "Caught exception reading view archive "
                                        + archiveFile.getAbsolutePath();
                                LOG.error(msg, e);
                            }
                        }
                    }

                    if (useExecutor && extractionRunnables.size() > 0) {
                        final ExecutorService executorService = getExecutorService(configuration);

                        for (Runnable runnable : extractionRunnables) {
                            // submit a new task for each archive that needs extraction
                            executorService.submit(runnable);
                        }
                    }

                    if (removeUndeployed) {
                        removeUndeployedViews();
                    }
                }
            } else {
                LOG.error("Could not create extracted view archive directory " + extractedArchivesPath + ".");
            }
        } catch (Exception e) {
            LOG.error("Caught exception reading view archives.", e);
        }
    }

    // read a view archive
    private void readViewArchive(ViewEntity viewDefinition, File archiveFile, File extractedArchiveDirFile,
            String serverVersion) {

        setViewStatus(viewDefinition, ViewEntity.ViewStatus.DEPLOYING,
                "Deploying " + extractedArchiveDirFile + ".");

        String extractedArchiveDirPath = extractedArchiveDirFile.getAbsolutePath();

        try {
            // extract the archive and get the class loader
            ClassLoader cl = extractor.extractViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile);

            ViewConfig viewConfig = archiveUtility.getViewConfigFromExtractedArchive(extractedArchiveDirPath,
                    configuration.isViewValidationEnabled());

            viewDefinition.setConfiguration(viewConfig);

            if (checkViewVersions(viewDefinition, serverVersion)) {
                setupViewDefinition(viewDefinition, cl);

                Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();

                for (InstanceConfig instanceConfig : viewConfig.getInstances()) {
                    ViewInstanceEntity instanceEntity = createViewInstanceDefinition(viewConfig, viewDefinition,
                            instanceConfig);
                    instanceEntity.setXmlDriven(true);
                    instanceDefinitions.add(instanceEntity);
                }
                persistView(viewDefinition, instanceDefinitions);

                setViewStatus(viewDefinition, ViewEntity.ViewStatus.DEPLOYED,
                        "Deployed " + extractedArchiveDirPath + ".");
            }
        } catch (Exception e) {
            String msg = "Caught exception loading view " + viewDefinition.getName();

            setViewStatus(viewDefinition, ViewEntity.ViewStatus.ERROR, msg + " : " + e.getMessage());
            LOG.error(msg, e);
        }
    }

    /**
     * Check the configured view max and min Ambari versions for the given view entity
     * against the given Ambari server version.
     *
     * @param view           the view
     * @param serverVersion  the server version
     *
     * @return true if the given server version >= min version && <= max version for the given view
     */
    protected boolean checkViewVersions(ViewEntity view, String serverVersion) {
        ViewConfig config = view.getConfiguration();

        return checkViewVersion(view, config.getMinAmbariVersion(), serverVersion, "minimum", 1, "less than")
                && checkViewVersion(view, config.getMaxAmbariVersion(), serverVersion, "maximum", -1,
                        "greater than");

    }

    // check the given version against the actual Ambari server version
    private boolean checkViewVersion(ViewEntity view, String version, String serverVersion, String label,
            int errValue, String errMsg) {

        if (version != null && !version.isEmpty()) {

            // make sure that the given version is a valid version string
            if (!version.matches(VIEW_AMBARI_VERSION_REGEXP)) {
                String msg = "The configured " + label + " Ambari version " + version + " for view "
                        + view.getName() + " is not valid.";

                setViewStatus(view, ViewEntity.ViewStatus.ERROR, msg);
                LOG.error(msg);
                return false;
            }

            int index = version.indexOf('*');

            int compVal = index == -1 ? VersionUtils.compareVersions(version, serverVersion)
                    : index > 0 ? VersionUtils.compareVersions(version.substring(0, index), serverVersion, index)
                            : 0;

            if (compVal == errValue) {
                String msg = "The Ambari server version " + serverVersion + " is " + errMsg + " the configured "
                        + label + " Ambari version " + version + " for view " + view.getName();

                setViewStatus(view, ViewEntity.ViewStatus.ERROR, msg);
                LOG.error(msg);
                return false;
            }
        }
        return true;
    }

    // persist the given view and its instances
    @Transactional
    private void persistView(ViewEntity viewDefinition, Set<ViewInstanceEntity> instanceDefinitions)
            throws Exception {
        // ensure that the view entity matches the db
        syncView(viewDefinition, instanceDefinitions);

        onDeploy(viewDefinition);

        // update the registry with the view instances
        for (ViewInstanceEntity instanceEntity : instanceDefinitions) {
            addInstanceDefinition(viewDefinition, instanceEntity);
            handlerList.addViewInstance(instanceEntity);
        }
    }

    // extract the view archive for the given path.
    protected static boolean extractViewArchive(String archivePath, ViewExtractor extractor,
            ViewArchiveUtility archiveUtility, Configuration configuration, boolean systemOnly) throws Exception {

        File viewDir = configuration.getViewsDir();

        String extractedArchivesPath = viewDir.getAbsolutePath() + File.separator + EXTRACTED_ARCHIVES_DIR;

        if (extractor.ensureExtractedArchiveDirectory(extractedArchivesPath)) {

            File archiveFile = archiveUtility.getFile(archivePath);

            ViewConfig viewConfig = archiveUtility.getViewConfigFromArchive(archiveFile);

            String commonName = viewConfig.getName();
            String version = viewConfig.getVersion();
            String viewName = ViewEntity.getViewName(commonName, version);

            String extractedArchiveDirPath = extractedArchivesPath + File.separator + viewName;
            File extractedArchiveDirFile = archiveUtility.getFile(extractedArchiveDirPath);

            if (!extractedArchiveDirFile.exists()) {
                ViewEntity viewDefinition = new ViewEntity(viewConfig, configuration, extractedArchiveDirPath);

                if (!systemOnly || viewDefinition.isSystem()) {
                    extractor.extractViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile);
                    return true;
                }
            }
        }
        return false;
    }

    // set the status of the given view.
    private void setViewStatus(ViewEntity viewDefinition, ViewEntity.ViewStatus status, String statusDetail) {
        viewDefinition.setStatus(status);
        viewDefinition.setStatusDetail(statusDetail);
    }

    // Get the view extraction thread pool
    private static synchronized ExecutorService getExecutorService(Configuration configuration) {
        if (executorService == null) {
            LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();

            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                    configuration.getViewExtractionThreadPoolCoreSize(),
                    configuration.getViewExtractionThreadPoolMaxSize(),
                    configuration.getViewExtractionThreadPoolTimeout(), TimeUnit.MILLISECONDS, queue);

            threadPoolExecutor.allowCoreThreadTimeOut(true);
            executorService = threadPoolExecutor;
        }
        return executorService;
    }

    /**
     * Factory method to create a view URL stream provider.
     *
     * @param viewContext  the view context
     *
     * @return a new view URL stream provider
     */
    protected ViewURLStreamProvider createURLStreamProvider(ViewContext viewContext) {
        ComponentSSLConfiguration sslConfiguration = ComponentSSLConfiguration.instance();
        org.apache.ambari.server.controller.internal.URLStreamProvider streamProvider = new org.apache.ambari.server.controller.internal.URLStreamProvider(
                configuration.getRequestConnectTimeout(), configuration.getRequestReadTimeout(),
                sslConfiguration.getTruststorePath(), sslConfiguration.getTruststorePassword(),
                sslConfiguration.getTruststoreType());
        return new ViewURLStreamProvider(viewContext, streamProvider);
    }

    /**
     * Factory method to create a view Ambari stream provider.
     *
     * @return a new view Ambari stream provider
     */
    protected ViewAmbariStreamProvider createAmbariStreamProvider() {
        ComponentSSLConfiguration sslConfiguration = ComponentSSLConfiguration.instance();
        org.apache.ambari.server.controller.internal.URLStreamProvider streamProvider = new org.apache.ambari.server.controller.internal.URLStreamProvider(
                DEFAULT_REQUEST_CONNECT_TIMEOUT, DEFAULT_REQUEST_READ_TIMEOUT, sslConfiguration.getTruststorePath(),
                sslConfiguration.getTruststorePassword(), sslConfiguration.getTruststoreType());
        return new ViewAmbariStreamProvider(streamProvider, ambariSessionManager, AmbariServer.getController());
    }
}