You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by js...@apache.org on 2014/11/10 22:32:09 UTC

[10/11] ambari git commit: AMBARI-7175. Add explicit stack service inheritance

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
deleted file mode 100644
index e014627..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
+++ /dev/null
@@ -1,975 +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.api.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
-import org.apache.ambari.server.metadata.ActionMetadata;
-import org.apache.ambari.server.state.ClientConfigFileDefinition;
-import org.apache.ambari.server.state.CommandScriptDefinition;
-import org.apache.ambari.server.state.ComponentInfo;
-import org.apache.ambari.server.state.ConfigHelper;
-import org.apache.ambari.server.state.CustomCommandDefinition;
-import org.apache.ambari.server.state.DependencyInfo;
-import org.apache.ambari.server.state.PropertyInfo;
-import org.apache.ambari.server.state.ServiceInfo;
-import org.apache.ambari.server.state.ServiceOsSpecific;
-import org.apache.ambari.server.state.StackInfo;
-import org.apache.ambari.server.state.stack.ConfigurationXml;
-import org.apache.ambari.server.state.stack.RepositoryXml;
-import org.apache.ambari.server.state.stack.ServiceMetainfoXml;
-import org.apache.ambari.server.state.stack.StackMetainfoXml;
-import org.apache.ambari.server.state.stack.UpgradePack;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import com.google.inject.Injector;
-
-/**
- * Helper methods for providing stack extension behavior -
- * Apache Jira: AMBARI-2819
- *
- * Stack extension processing is done in two steps. At first step, we parse
- * all information for every stack from stack files. At second step, we
- * go through parent and perform inheritance where needed. At both steps,
- * stacks are processed at random order, that's why extension implementation
- * for any new stack/service/component property should also consist of two
- * separate steps (otherwise child may happen to be processed before parent's
- * properties are populated).
- */
-public class StackExtensionHelper {
-  private ActionMetadata actionMetadata;
-
-  private File stackRoot;
-  private final static Logger LOG = LoggerFactory.getLogger(StackExtensionHelper.class);
-  private final Map<String, StackInfo> stackVersionMap = new HashMap<String,
-    StackInfo>();
-  private Map<String, List<StackInfo>> stackParentsMap = null;
-  public final static String HOOKS_FOLDER_NAME = "hooks";
-  private static final String PACKAGE_FOLDER_NAME = "package";
-
-  private static final Map<Class<?>, JAXBContext> _jaxbContexts =
-      new HashMap<Class<?>, JAXBContext> ();
-  static {
-    try {
-      JAXBContext ctx = JAXBContext.newInstance(StackMetainfoXml.class,
-          RepositoryXml.class, ConfigurationXml.class, UpgradePack.class);
-      _jaxbContexts.put(StackMetainfoXml.class, ctx);
-      _jaxbContexts.put(RepositoryXml.class, ctx);
-      _jaxbContexts.put(ConfigurationXml.class, ctx);
-      _jaxbContexts.put(UpgradePack.class, ctx);
-      _jaxbContexts.put(ServiceMetainfoXml.class, JAXBContext.newInstance(ServiceMetainfoXml.class));
-    } catch (JAXBException e) {
-      throw new RuntimeException (e);
-    }
-  }
-
-  /**
-   * Note: constructor does not perform inialisation now. After instance
-   * creation, you have to call fillInfo() manually
-   */
-  public StackExtensionHelper(Injector injector, File stackRoot) {
-    this.stackRoot = stackRoot;
-    this.actionMetadata = injector.getInstance(ActionMetadata.class);
-  }
-
-
-  /**
-   * Must be manually called after creation of StackExtensionHelper instance
-   */
-  public void fillInfo() throws Exception {
-    if (stackParentsMap != null) {
-      throw new AmbariException("fillInfo() method has already been called");
-    }
-    File[] stackFiles = stackRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
-    for (File stack : stackFiles) {
-      if (stack.isFile()) {
-        continue;
-      }
-      for (File stackFolder : stack.listFiles(AmbariMetaInfo.FILENAME_FILTER)) {
-        if (stackFolder.isFile()) {
-          continue;
-        }
-        String stackName = stackFolder.getParentFile().getName();
-        String stackVersion = stackFolder.getName();
-        stackVersionMap.put(stackName + stackVersion, getStackInfo(stackFolder));
-      }
-    }
-    stackParentsMap = getParentStacksInOrder(stackVersionMap.values());
-  }
-
-  void mergeStacks(StackInfo parentStack,
-      StackInfo resultStack) {
-    if(parentStack.getConfigTypes() != null) {
-      resultStack.getConfigTypes().putAll(parentStack.getConfigTypes());
-    }
-    List<PropertyInfo> mergedProperties = new ArrayList<PropertyInfo>();
-    mergeProperties(resultStack.getProperties(), parentStack.getProperties(), mergedProperties, resultStack.getConfigTypes());
-    resultStack.setProperties(mergedProperties);
-  }
-
-  ServiceInfo mergeServices(ServiceInfo parentService,
-                                    ServiceInfo childService) {
-    ServiceInfo mergedServiceInfo = new ServiceInfo();
-    mergedServiceInfo.setSchemaVersion(childService.getSchemaVersion());
-    mergedServiceInfo.setName(childService.getName());
-    mergedServiceInfo.setComment(childService.getComment() != null ?
-        childService.getComment() :
-        parentService.getComment());
-    mergedServiceInfo.setVersion(childService.getVersion());
-    mergedServiceInfo.setDisplayName(
-        childService.getDisplayName() != null ?
-            childService.getDisplayName() :
-            parentService.getDisplayName());
-    mergedServiceInfo.setConfigDependencies(
-        childService.getConfigDependencies() != null ?
-            childService.getConfigDependencies() :
-            parentService.getConfigDependencies() != null ?
-                parentService.getConfigDependencies() :
-                Collections.<String>emptyList());
-    mergedServiceInfo.setExcludedConfigTypes(
-      childService.getExcludedConfigTypes() != null ?
-        childService.getExcludedConfigTypes() :
-        parentService.getExcludedConfigTypes() != null ?
-          parentService.getExcludedConfigTypes() :
-          Collections.<String>emptySet()
-    );
-    mergedServiceInfo.setRequiredServices(
-        childService.getRequiredServices() != null ?
-          childService.getRequiredServices() :
-          parentService.getRequiredServices() != null ?
-            parentService.getRequiredServices() :
-            Collections.<String>emptyList()
-      );
-
-    mergedServiceInfo.setRestartRequiredAfterChange(
-            (childService.isRestartRequiredAfterChange() != null)
-                    ? childService.isRestartRequiredAfterChange()
-                    : parentService.isRestartRequiredAfterChange());
-    mergedServiceInfo.setMonitoringService(
-            (childService.isMonitoringService() != null)
-                    ? childService.isMonitoringService()
-                    : parentService.isMonitoringService());
-
-    Map<String, ServiceOsSpecific> osSpecific = childService.getOsSpecifics();
-    if (! osSpecific.isEmpty()) {
-      mergedServiceInfo.setOsSpecifics(childService.getOsSpecifics());
-    } else {
-      mergedServiceInfo.setOsSpecifics(parentService.getOsSpecifics());
-    }
-
-    mergedServiceInfo.setConfigTypes(new HashMap<String, Map<String, Map<String, String>>>());
-    if(childService.getConfigTypes() != null) {
-      mergedServiceInfo.getConfigTypes().putAll(childService.getConfigTypes());
-    }
-    if(parentService.getConfigTypes() != null) {
-      mergedServiceInfo.getConfigTypes().putAll(parentService.getConfigTypes());
-    }
-
-    CommandScriptDefinition commandScript = childService.getCommandScript();
-    if (commandScript != null) {
-       mergedServiceInfo.setCommandScript(childService.getCommandScript());
-    } else {
-      mergedServiceInfo.setCommandScript(parentService.getCommandScript());
-    }
-
-    String servicePackageFolder = childService.getServicePackageFolder();
-    if (servicePackageFolder != null) {
-      mergedServiceInfo.setServicePackageFolder(servicePackageFolder);
-    } else {
-      mergedServiceInfo.setServicePackageFolder(
-              parentService.getServicePackageFolder());
-    }
-
-    // Merge custom command definitions for service
-    List<CustomCommandDefinition> mergedCustomCommands =
-            mergeCustomCommandLists(parentService.getCustomCommands(),
-                    childService.getCustomCommands());
-    mergedServiceInfo.setCustomCommands(mergedCustomCommands);
-
-    // metrics
-    if (null != childService.getMetricsFile())
-      mergedServiceInfo.setMetricsFile(childService.getMetricsFile());
-    else if (null != parentService.getMetricsFile())
-      mergedServiceInfo.setMetricsFile(parentService.getMetricsFile());
-
-    // alerts
-    if (null != childService.getAlertsFile())
-      mergedServiceInfo.setAlertsFile(childService.getAlertsFile());
-    else if (null != parentService.getAlertsFile())
-      mergedServiceInfo.setAlertsFile(parentService.getAlertsFile());
-
-    populateComponents(mergedServiceInfo, parentService, childService);
-    mergeProperties(childService.getProperties(), parentService.getProperties(),
-        mergedServiceInfo.getProperties(), childService.getConfigTypes());
-    // Add all parent config dependencies
-    if (parentService.getConfigDependencies() != null && !parentService
-        .getConfigDependencies().isEmpty()) {
-      for (String configDep : parentService.getConfigDependencies()) {
-        if (!mergedServiceInfo.getConfigDependencies().contains(configDep)) {
-          mergedServiceInfo.getConfigDependencies().add(configDep);
-        }
-      }
-    }
-    return mergedServiceInfo;
-  }
-
-  public void mergeProperties(List<PropertyInfo> childProperties,
-                              List<PropertyInfo> parentProperties, List<PropertyInfo> mergedProperties, Map<String,
-      Map<String, Map<String, String>>> childConfigTypes) {
-    // Add child properties not deleted
-    Map<String, Set<String>> deleteMap = new HashMap<String, Set<String>>();
-    Map<String, Set<String>> appendMap = new HashMap<String, Set<String>>();
-    for (PropertyInfo propertyInfo : childProperties) {
-      if (!propertyInfo.isDeleted()) {
-        mergedProperties.add(propertyInfo);
-        if (appendMap.containsKey(propertyInfo.getName())) {
-          appendMap.get(propertyInfo.getName()).add(propertyInfo.getFilename());
-        } else {
-          Set<String> filenames = new HashSet<String>();
-          filenames.add(propertyInfo.getFilename());
-          appendMap.put(propertyInfo.getName(), filenames);
-        }
-      } else {
-        if (deleteMap.containsKey(propertyInfo.getName())) {
-          deleteMap.get(propertyInfo.getName()).add(propertyInfo.getFilename());
-        } else {
-          Set<String> filenames = new HashSet<String>();
-          filenames.add(propertyInfo.getFilename());
-          deleteMap.put(propertyInfo.getName(), filenames);
-        }
-      }
-    }
-    // Add all parent properties
-    for (PropertyInfo parentPropertyInfo : parentProperties) {
-      String configType = ConfigHelper.fileNameToConfigType(parentPropertyInfo.getFilename());
-      boolean disableInherit = false;
-      if (childConfigTypes.containsKey(configType)){
-        disableInherit =
-          childConfigTypes.get(configType).get(Supports.KEYWORD).get(Supports.DO_NOT_EXTEND.getPropertyName()).equals("true");
-      }
-      if (!deleteMap.containsKey(parentPropertyInfo.getName()) && !(appendMap
-          .containsKey(parentPropertyInfo.getName())
-        && appendMap.get(parentPropertyInfo.getName())
-          .contains(parentPropertyInfo.getFilename())) && !disableInherit) {
-        mergedProperties.add(parentPropertyInfo);
-      }
-    }
-  }
-
-
-  /**
-   * Merges component sets of parentService and childService and writes result
-   * to mergedServiceInfo
-   */
-  private void populateComponents(ServiceInfo mergedServiceInfo, ServiceInfo parentService,
-                                  ServiceInfo childService) {
-    // Add all child components to service
-    List<String> deleteList = new ArrayList<String>();
-    List<String> appendList = new ArrayList<String>();
-
-    for (ComponentInfo childComponent : childService.getComponents()) {
-      if (!childComponent.isDeleted()) {
-        ComponentInfo parentComponent = parentService.getComponentByName(childComponent.getName());
-        if (parentComponent != null) { // If parent has similar component
-          ComponentInfo mergedComponent = mergeComponents(parentComponent,
-                  childComponent);
-          mergedServiceInfo.getComponents().add(mergedComponent);
-          appendList.add(mergedComponent.getName());
-        } else {
-          mergedServiceInfo.getComponents().add(childComponent);
-          appendList.add(childComponent.getName());
-        }
-      } else {
-        deleteList.add(childComponent.getName());
-      }
-    }
-    // Add remaining parent components
-    for (ComponentInfo parentComponent : parentService.getComponents()) {
-      if (!deleteList.contains(parentComponent.getName()) && !appendList
-              .contains(parentComponent.getName())) {
-        mergedServiceInfo.getComponents().add(parentComponent);
-      }
-    }
-  }
-
-  ComponentInfo mergeComponents(ComponentInfo parent, ComponentInfo child) {
-    ComponentInfo result = new ComponentInfo(child); // cloning child
-    CommandScriptDefinition commandScript = child.getCommandScript();
-    String category = child.getCategory();
-    String cardinality = child.getCardinality();
-    List<String> clientsToUpdateConfigs = child.getClientsToUpdateConfigs();
-
-    if (commandScript != null) {
-      result.setCommandScript(child.getCommandScript());
-    } else {
-      result.setCommandScript(parent.getCommandScript());
-    }
-    //keep the same semantic as for ServiceInfo
-    result.setDisplayName(
-        child.getDisplayName() != null ?
-            child.getDisplayName() : parent.getDisplayName());
-
-    result.setConfigDependencies(
-        child.getConfigDependencies() != null ?
-            child.getConfigDependencies() : parent.getConfigDependencies());
-
-
-    //Merge client config file definitions
-    List<ClientConfigFileDefinition> clientConfigFiles = child.getClientConfigFiles();
-    if (clientConfigFiles != null) {
-      result.setClientConfigFiles(child.getClientConfigFiles());
-    } else {
-      result.setClientConfigFiles(parent.getClientConfigFiles());
-    }
-    if (clientsToUpdateConfigs != null) {
-      result.setClientsToUpdateConfigs(child.getClientsToUpdateConfigs());
-    } else {
-      result.setClientsToUpdateConfigs(parent.getClientsToUpdateConfigs());
-    }
-    // Merge custom command definitions for service
-    List<CustomCommandDefinition> mergedCustomCommands =
-                mergeCustomCommandLists(parent.getCustomCommands(),
-                            child.getCustomCommands());
-    result.setCustomCommands(mergedCustomCommands);
-
-    if (category != null) {
-      result.setCategory(child.getCategory());
-    } else {
-      result.setCategory(parent.getCategory());
-    }
-
-    if (cardinality != null) {
-      result.setCardinality(child.getCardinality());
-    } else {
-      result.setCardinality(parent.getCardinality());
-    }
-
-    result.setDependencies(
-        child.getDependencies() == null ?
-            parent.getDependencies() :
-            parent.getDependencies() == null ?
-                child.getDependencies() :
-                mergeComponentDependencies(parent.getDependencies(),
-                    child.getDependencies()));
-
-    return result;
-  }
-
-  List<DependencyInfo> mergeComponentDependencies(
-      List<DependencyInfo> parentList,
-      List<DependencyInfo> childList) {
-
-    List<DependencyInfo> mergedList =
-        new ArrayList<DependencyInfo>(childList);
-    List<String> existingNames = new ArrayList<String>();
-
-    for (DependencyInfo childDI : childList) {
-      existingNames.add(childDI.getName());
-    }
-    for (DependencyInfo parentsDI : parentList) {
-      if (! existingNames.contains(parentsDI.getName())) {
-        mergedList.add(parentsDI);
-        existingNames.add(parentsDI.getName());
-      }
-    }
-    return mergedList;
-  }
-
-
-  private List<CustomCommandDefinition> mergeCustomCommandLists(
-          List<CustomCommandDefinition> parentList,
-          List<CustomCommandDefinition> childList) {
-    List<CustomCommandDefinition> mergedList =
-            new ArrayList<CustomCommandDefinition>(childList);
-    List<String> existingNames = new ArrayList<String>();
-    for (CustomCommandDefinition childCCD : childList) {
-      existingNames.add(childCCD.getName());
-    }
-    for (CustomCommandDefinition parentsCCD : parentList) {
-      if (! existingNames.contains(parentsCCD.getName())) {
-        mergedList.add(parentsCCD);
-        existingNames.add(parentsCCD.getName());
-      }
-    }
-    return mergedList;
-  }
-
-
-  public List<ServiceInfo> getAllApplicableServices(StackInfo stackInfo) {
-    LinkedList<StackInfo> parents = (LinkedList<StackInfo>)
-      stackParentsMap.get(stackInfo.getVersion());
-
-    if (parents == null || parents.isEmpty()) {
-      return stackInfo.getServices();
-    }
-    // Add child to the end of extension list
-    parents.addFirst(stackInfo);
-    ListIterator<StackInfo> lt = parents.listIterator(parents.size());
-    // Map services with unique names
-    Map<String, ServiceInfo> serviceInfoMap = new HashMap<String,
-      ServiceInfo>();
-    List<ServiceInfo> serviceInfoList = null;
-    // Iterate with oldest parent first - all stacks are populated
-    StackInfo parentStack = null;
-    while(lt.hasPrevious()) {
-      if (parentStack == null) {
-        parentStack = lt.previous();
-        serviceInfoList = parentStack.getServices();
-        for (ServiceInfo service : serviceInfoList){
-          if (!service.isDeleted()) {
-            serviceInfoMap.put(service.getName(), service);
-          }
-        }
-        continue;
-      }
-      StackInfo currentStackInfo = lt.previous();
-      serviceInfoList = currentStackInfo.getServices();
-
-      mergeStacks(parentStack, currentStackInfo);
-
-      for (ServiceInfo service : serviceInfoList) {
-        ServiceInfo existingService = serviceInfoMap.get(service.getName());
-        if (service.isDeleted()) {
-          serviceInfoMap.remove(service.getName());
-          continue;
-        }
-
-        if (existingService == null && !service.isDeleted()) {
-          serviceInfoMap.put(service.getName(), service);
-        } else {
-          // Redefined service - merge with parent
-          ServiceInfo newServiceInfo = mergeServices(existingService, service);
-          serviceInfoMap.put(service.getName(), newServiceInfo);
-        }
-
-        // remove 'excluded-config-types' from configTypes
-        ServiceInfo serviceInfo = serviceInfoMap.get(service.getName());
-        if(serviceInfo.getExcludedConfigTypes() != null) {
-          Iterator<Map.Entry<String,Map<String,Map<String,String>>>> configTypesItetator = serviceInfo.getConfigTypes().entrySet().iterator();
-
-          while(configTypesItetator.hasNext()) {
-            Map.Entry<String,Map<String,Map<String,String>>> configTypeMap = configTypesItetator.next();
-
-            if(serviceInfo.getExcludedConfigTypes().contains(configTypeMap.getKey())) {
-              configTypesItetator.remove();
-            }
-          }
-        }
-
-      }
-      parentStack = currentStackInfo;
-    }
-    return new ArrayList<ServiceInfo>(serviceInfoMap.values());
-  }
-
-
-  /**
-   * Determines exact hooks folder (subpath from stackRoot to hooks directory)
-   * to use for a given stack. If given stack
-   * has not hooks folder, inheritance hierarhy is queried.
-   * @param stackInfo stack to work with
-   */
-  public String resolveHooksFolder(StackInfo stackInfo) throws AmbariException {
-    // Determine hooks folder for stack
-    String stackId = String.format("%s-%s",
-            stackInfo.getName(), stackInfo.getVersion());
-    String hooksFolder = stackInfo.getStackHooksFolder();
-    if (hooksFolder == null) {
-      // Try to get parent's
-      List<StackInfo> parents = getParents(stackInfo);
-      for (StackInfo parent : parents) {
-        hooksFolder = parent.getStackHooksFolder();
-        if (hooksFolder != null) {
-          break;
-        }
-      }
-    }
-    if (hooksFolder == null) {
-      String message = String.format(
-              "Can not determine hooks dir for stack %s",
-              stackId);
-      LOG.debug(message);
-    }
-    return hooksFolder;
-  }
-
-  void populateServicesForStack(StackInfo stackInfo) throws
-      ParserConfigurationException, SAXException,
-      XPathExpressionException, IOException, JAXBException {
-    List<ServiceInfo> services = new ArrayList<ServiceInfo>();
-
-    File servicesFolder = new File(stackRoot.getAbsolutePath() + File
-      .separator + stackInfo.getName() + File.separator + stackInfo.getVersion()
-      + File.separator + AmbariMetaInfo.SERVICES_FOLDER_NAME);
-    if (!servicesFolder.exists()) {
-      LOG.info("No services defined for stack: " + stackInfo.getName() +
-      "-" + stackInfo.getVersion());
-    } else {
-      try {
-        File[] servicesFolders = servicesFolder.listFiles(AmbariMetaInfo
-          .FILENAME_FILTER);
-        if (servicesFolders == null) {
-          String message = String.format("No service folders found at %s",
-                  servicesFolder.getAbsolutePath());
-          throw new AmbariException(message);
-        }
-        // Iterate over service folders
-        for (File serviceFolder : servicesFolders) {
-          if (!serviceFolder.isDirectory())
-            continue;
-          // Get metainfo schema format version
-          File metainfoFile = new File(serviceFolder.getAbsolutePath()
-                  + File.separator + AmbariMetaInfo.SERVICE_METAINFO_FILE_NAME);
-          // get metrics file, if it exists
-          File metricsJson = new File(serviceFolder.getAbsolutePath()
-            + File.separator + AmbariMetaInfo.SERVICE_METRIC_FILE_NAME);
-
-          File alertsJson = new File(serviceFolder.getAbsolutePath() +
-              File.separator + AmbariMetaInfo.SERVICE_ALERT_FILE_NAME);
-
-          if (!metainfoFile.exists()) {
-            LOG.warn("Service folder " + serviceFolder.getAbsolutePath() + " doesn't contain metainfo file. Ignoring it.");
-            continue;
-          }
-
-          //Reading v2 service metainfo (may contain multiple services)
-          // Get services from metadata
-          try {
-            ServiceMetainfoXml smiv2x =
-                unmarshal(ServiceMetainfoXml.class, metainfoFile);
-            List<ServiceInfo> serviceInfos = smiv2x.getServices();
-            for (ServiceInfo serviceInfo : serviceInfos) {
-              serviceInfo.setSchemaVersion(AmbariMetaInfo.SCHEMA_VERSION_2);
-
-              // Find service package folder
-              String servicePackageDir = resolveServicePackageFolder(
-                  stackRoot.getAbsolutePath(), stackInfo,
-                  serviceFolder.getName(), serviceInfo.getName());
-              serviceInfo.setServicePackageFolder(servicePackageDir);
-
-              // process metrics.json
-              if (metricsJson.exists())
-                serviceInfo.setMetricsFile(metricsJson);
-              if (alertsJson.exists())
-                serviceInfo.setAlertsFile(alertsJson);
-
-              // Get all properties from all "configs/*-site.xml" files
-              setPropertiesFromConfigs(serviceFolder, serviceInfo);
-
-              // Add now to be removed while iterating extension graph
-              services.add(serviceInfo);
-            }
-          } catch (JAXBException e) {
-            LOG.warn("Error while parsing metainfo.xml for a service: " + serviceFolder.getAbsolutePath(), e);
-          }
-        }
-      } catch (Exception e) {
-        LOG.error("Error while parsing metainfo.xml for a service", e);
-      }
-    }
-
-    stackInfo.getServices().addAll(services);
-
-    // add service check actions from the target stack
-    for(ServiceInfo serviceInfo : stackInfo.getServices()) {
-      if(serviceInfo.getCommandScript() != null) {
-        actionMetadata.addServiceCheckAction(serviceInfo.getName());
-      }
-    }
-
-  }
-
-
-  /**
-   * Determines exact service directory that contains scripts and templates
-   * for service. If given stack has not this folder, inheritance hierarhy is
-   * queried.
-   */
-  String resolveServicePackageFolder(String stackRoot,
-                                     StackInfo stackInfo, String serviceFolderName,
-                                     String serviceName) throws AmbariException {
-    String stackId = String.format("%s-%s",
-            stackInfo.getName(), stackInfo.getVersion());
-    String expectedSubPath = stackInfo.getName() + File.separator +
-                    stackInfo.getVersion() + File.separator +
-                    AmbariMetaInfo.SERVICES_FOLDER_NAME +
-                    File.separator + serviceFolderName + File.separator +
-                    PACKAGE_FOLDER_NAME;
-    File packageDir = new File(stackRoot + File.separator + expectedSubPath);
-    String servicePackageFolder = null;
-    if (packageDir.isDirectory()) {
-      servicePackageFolder = expectedSubPath;
-      String message = String.format(
-              "Service package folder for service %s" +
-                      " for stack %s has been resolved to %s",
-              serviceName, stackId, servicePackageFolder);
-      LOG.debug(message);
-    } else {
-        String message = String.format(
-                "Service package folder %s for service %s " +
-                        " for stack %s does not exist.",
-                packageDir.getAbsolutePath(), serviceName, stackId);
-        LOG.debug(message);
-    }
-    return servicePackageFolder;
-  }
-
-
-  public List<StackInfo> getAllAvailableStacks() {
-    return new ArrayList<StackInfo>(stackVersionMap.values());
-  }
-
-  public List<StackInfo> getParents(StackInfo stackInfo) {
-    return stackParentsMap.get(stackInfo.getVersion());
-  }
-
-  private Map<String, List<StackInfo>> getParentStacksInOrder(
-      Collection<StackInfo> stacks) {
-    Map<String, List<StackInfo>> parentStacksMap = new HashMap<String,
-      List<StackInfo>>();
-
-    for (StackInfo child : stacks) {
-      List<StackInfo> parentStacks = new LinkedList<StackInfo>();
-      parentStacksMap.put(child.getVersion(), parentStacks);
-      while (child.getParentStackVersion() != null && !child
-        .getParentStackVersion().isEmpty() && !child.getVersion().equals
-        (child.getParentStackVersion())) {
-        String key = child.getName() + child.getParentStackVersion();
-        if (stackVersionMap.containsKey(key)) {
-          StackInfo parent = stackVersionMap.get(key);
-          parentStacks.add(parent);
-          child = parent;
-        } else {
-          LOG.info("Unknown parent stack version: " + child
-            .getParentStackVersion() + ", for stack: " + child.getName() + " " +
-            child.getVersion());
-          break;
-        }
-      }
-    }
-    return parentStacksMap;
-  }
-
-
-  /**
-   * Determines schema version of a given metainfo file
-   * @param stackMetainfoFile  xml file
-   */
-  String getSchemaVersion(File stackMetainfoFile) throws IOException,
-          ParserConfigurationException, SAXException, XPathExpressionException {
-    // Using XPath to get a single value from an metainfo file
-    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-    DocumentBuilder builder = factory.newDocumentBuilder();
-    Document doc = builder.parse(stackMetainfoFile);
-    XPathFactory xPathfactory = XPathFactory.newInstance();
-    XPath xpath = xPathfactory.newXPath();
-    XPathExpression schemaPath = xpath.compile("/metainfo/schemaVersion[1]");
-
-    String value = schemaPath.evaluate(doc).trim();
-    if ( "".equals(value) || // If schemaVersion is not defined
-            AmbariMetaInfo.SCHEMA_VERSION_2.equals(value)) {
-      return AmbariMetaInfo.SCHEMA_VERSION_2;
-    } else {
-      String message = String.format("Unknown schema version %s at file " +
-              "%s", value, stackMetainfoFile.getAbsolutePath());
-      throw new AmbariException(message);
-    }
-
-  }
-
-  /**
-   * Get populated stackInfo for the stack definition at the provided path.
-   * @param stackVersionFolder Path to stack definition.
-   * @return StackInfo StackInfo object
-   * @throws JAXBException
-   */
-  private StackInfo getStackInfo(File stackVersionFolder) throws JAXBException {
-    StackInfo stackInfo = new StackInfo();
-
-    stackInfo.setName(stackVersionFolder.getParentFile().getName());
-    stackInfo.setVersion(stackVersionFolder.getName());
-
-    // Get metainfo from file
-    File stackMetainfoFile = new File(stackVersionFolder.getAbsolutePath()
-        + File.separator + AmbariMetaInfo.STACK_METAINFO_FILE_NAME);
-
-    if (stackMetainfoFile.exists()) {
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Reading stack version metainfo from file "
-            + stackMetainfoFile.getAbsolutePath());
-      }
-
-      StackMetainfoXml smx = unmarshal(StackMetainfoXml.class, stackMetainfoFile);
-
-      stackInfo.setMinUpgradeVersion(smx.getVersion().getUpgrade());
-      stackInfo.setActive(smx.getVersion().isActive());
-      stackInfo.setParentStackVersion(smx.getExtends());
-
-      // Populating hooks dir for stack
-      String hooksSubPath = stackInfo.getName() + File.separator +
-              stackInfo.getVersion() + File.separator + HOOKS_FOLDER_NAME;
-      String hooksAbsPath = stackVersionFolder.getAbsolutePath() +
-              File.separator + HOOKS_FOLDER_NAME;
-      if (new File(hooksAbsPath).exists()) {
-        stackInfo.setStackHooksFolder(hooksSubPath);
-      } else {
-        String message = String.format("Hooks folder %s does not exist",
-                hooksAbsPath);
-        LOG.debug(message);
-      }
-
-      String rcoFileLocation = stackVersionFolder.getAbsolutePath() +
-              File.separator + AmbariMetaInfo.RCO_FILE_NAME;
-      if (new File(rcoFileLocation).exists())
-        stackInfo.setRcoFileLocation(rcoFileLocation);
-
-      setStackPropertiesFromConfigs(stackInfo);
-    }
-
-    try {
-      // Read the service and available configs for this stack
-      populateServicesForStack(stackInfo);
-    } catch (Exception e) {
-      LOG.error("Exception caught while populating services for stack: " +
-        stackInfo.getName() + "-" + stackInfo.getVersion());
-      e.printStackTrace();
-    }
-    return stackInfo;
-  }
-
-  private void populateStackProperties(StackInfo stackInfo, File configFile) throws JAXBException {
-    ConfigurationXml configuration = unmarshal(ConfigurationXml.class, configFile);
-    String fileName = configFile.getName();
-    stackInfo.getProperties().addAll(getProperties(configuration, fileName));
-    String configType = ConfigHelper.fileNameToConfigType(fileName);
-
-    addConfigType(stackInfo.getConfigTypes(), configType);
-    setConfigTypeAttributes(stackInfo.getConfigTypes(), configuration, configType);
-  }
-
-  /**
-   * Get all properties from all "configs/*.xml" files. See {@see AmbariMetaInfo#SERVICE_CONFIG_FILE_NAME_POSTFIX}
-   */
-  void setStackPropertiesFromConfigs(StackInfo stackInfo) {
-    File configsFolder = new File(stackRoot.getAbsolutePath() + File
-        .separator + stackInfo.getName() + File.separator + stackInfo.getVersion()
-        + File.separator + AmbariMetaInfo.SERVICE_CONFIG_FOLDER_NAME);
-
-    if (!configsFolder.exists() || !configsFolder.isDirectory())
-      return;
-
-    File[] configFiles = configsFolder.listFiles(AmbariMetaInfo.FILENAME_FILTER);
-    if (configFiles != null) {
-      for (File configFile : configFiles) {
-        if (configFile.getName().endsWith(AmbariMetaInfo.SERVICE_CONFIG_FILE_NAME_POSTFIX)) {
-          try {
-            populateStackProperties(stackInfo, configFile);
-          } catch (Exception e) {
-            LOG.error("Could not load configuration for " + configFile, e);
-          }
-        }
-      }
-    }
-  }
-
-  private List<PropertyInfo> getProperties(ConfigurationXml configuration, String fileName) {
-    List<PropertyInfo> list = new ArrayList<PropertyInfo>();
-    for (PropertyInfo pi : configuration.getProperties()) {
-      pi.setFilename(fileName);
-      list.add(pi);
-    }
-    return list;
-  }
-
-  /**
-   * Add properties and config type's properties from configuration file
-   */
-  void populateServiceProperties(File configFile, ServiceInfo serviceInfo) throws JAXBException {
-    ConfigurationXml configuration = unmarshal(ConfigurationXml.class, configFile);
-    String fileName = configFile.getName();
-    serviceInfo.getProperties().addAll(getProperties(configuration, fileName));
-    String configType = ConfigHelper.fileNameToConfigType(fileName);
-
-    addConfigType(serviceInfo.getConfigTypes(), configType);
-    setConfigTypeAttributes(serviceInfo.getConfigTypes(), configuration, configType);
-  }
-
-  void setConfigTypeAttributes(Map<String, Map<String, Map<String, String>>> configTypes, ConfigurationXml configuration, String configType) {
-    for (Map.Entry<QName, String> attribute : configuration.getAttributes().entrySet()) {
-      for (Supports supportsProperty : Supports.values()) {
-        String attributeName = attribute.getKey().getLocalPart();
-        String attributeValue = attribute.getValue();
-        if (attributeName.equals(supportsProperty.getXmlAttributeName())) {
-          addConfigTypeProperty(configTypes, configType, Supports.KEYWORD,
-              supportsProperty.getPropertyName(), Boolean.valueOf(attributeValue).toString());
-        }
-      }
-    }
-  }
-
-  void addConfigType(Map<String, Map<String, Map<String, String>>> configTypes, String configType) {
-    configTypes.put(configType, new HashMap<String, Map<String, String>>());
-
-    Map<String, Map<String, String>> properties = configTypes.get(configType);
-    Map<String, String> supportsProperties = new HashMap<String, String>();
-    for (Supports supportsProperty : Supports.values()) {
-      supportsProperties.put(supportsProperty.getPropertyName(), supportsProperty.getDefaultValue());
-    }
-    properties.put(Supports.KEYWORD, supportsProperties);
-  }
-
-  /**
-   * Populate ServiceInfo#configTypes with default entries based on ServiceInfo#configDependencies property
-   */
-  void populateConfigTypesFromDependencies(ServiceInfo serviceInfo) {
-    List<PropertyInfo> configurations = serviceInfo.getProperties();
-    if (configurations != null) {
-      Map<String, Map<String, Map<String, String>>> configTypes = new HashMap<String, Map<String, Map<String, String>>>();
-      for (PropertyInfo configuration : configurations) {
-        String configType = ConfigHelper.fileNameToConfigType(configuration.getFilename());
-
-        if (!configTypes.containsKey(configType)) {
-          Map<String, Map<String, String>> properties = new HashMap<String, Map<String, String>>();
-          Map<String, String> supportsProperties = new HashMap<String, String>();
-          for (Supports supportsProperty : Supports.values()) {
-            supportsProperties.put(supportsProperty.getPropertyName(), supportsProperty.getDefaultValue());
-          }
-          properties.put(Supports.KEYWORD, supportsProperties);
-          configTypes.put(configType, properties);
-        }
-      }
-      serviceInfo.setConfigTypes(configTypes);
-    }
-  }
-
-  /**
-   * Put new property entry to ServiceInfo#configTypes collection for specified configType
-   */
-  void addConfigTypeProperty(Map<String, Map<String, Map<String, String>>> configTypes, String configType,
-      String propertiesGroupName, String key, String value) {
-   if (configTypes != null && configTypes.containsKey(configType)) {
-      Map<String, Map<String, String>> configDependencyProperties = configTypes.get(configType);
-      if (!configDependencyProperties.containsKey(propertiesGroupName)) {
-        configDependencyProperties.put(propertiesGroupName, new HashMap<String, String>());
-      }
-      Map<String, String> propertiesGroup = configDependencyProperties.get(propertiesGroupName);
-      propertiesGroup.put(key, value);
-    }
-  }
-
-  /**
-   * Get all properties from all "configs/*.xml" files. See {@see AmbariMetaInfo#SERVICE_CONFIG_FILE_NAME_POSTFIX}
-   */
-  void setPropertiesFromConfigs(File serviceFolder, ServiceInfo serviceInfo) {
-
-    File serviceConfigFolder = new File(serviceFolder.getAbsolutePath()
-            + File.separator + serviceInfo.getConfigDir());
-
-    if (!serviceConfigFolder.exists() || !serviceConfigFolder.isDirectory())
-      return;
-
-    File[] configFiles = serviceConfigFolder.listFiles(AmbariMetaInfo.FILENAME_FILTER);
-    if (configFiles != null) {
-      for (File configFile : configFiles) {
-        if (configFile.getName().endsWith(AmbariMetaInfo.SERVICE_CONFIG_FILE_NAME_POSTFIX)) {
-          try {
-            populateServiceProperties(configFile, serviceInfo);
-          } catch (Exception e) {
-            LOG.error("Could not load configuration for " + configFile, e);
-          }
-        }
-      }
-    }
-  }
-
-  public static <T> T unmarshal(Class<T> clz, File file) throws JAXBException {
-    Unmarshaller u = _jaxbContexts.get(clz).createUnmarshaller();
-
-    return clz.cast(u.unmarshal(file));
-  }
-
-  /**
-   * Service configuration-types can support different abilities. This
-   * enumerates the various abilities that configuration-types can support.
-   *
-   * For example, Hadoop configuration types like 'core-site' and 'hdfs-site'
-   * can support the ability to define certain configs as 'final'.
-   */
-  protected enum Supports {
-
-    FINAL("supports_final"),
-    ADDING_FORBIDDEN("supports_adding_forbidden"),
-    DO_NOT_EXTEND("supports_do_not_extend");
-
-    public static final String KEYWORD = "supports";
-
-    private String defaultValue;
-    private String xmlAttributeName;
-
-    private Supports(String xmlAttributeName) {
-      this(xmlAttributeName, Boolean.FALSE.toString());
-    }
-
-    private Supports(String xmlAttributeName, String defaultValue) {
-      this.defaultValue = defaultValue;
-      this.xmlAttributeName = xmlAttributeName;
-    }
-
-    public String getDefaultValue() {
-      return defaultValue;
-    }
-
-    public String getXmlAttributeName() {
-      return xmlAttributeName;
-    }
-
-    public String getPropertyName() {
-      return name().toLowerCase();
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
index 4808a77..1899dde 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
@@ -30,6 +30,7 @@ import java.util.Set;
 import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.StackAccessException;
@@ -242,8 +243,12 @@ public class AmbariActionExecutionHelper {
             cluster.getService(serviceName)
               .getServiceComponent(componentName).getServiceComponentHosts();
           candidateHosts.addAll(componentHosts.keySet());
-          componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-            stackId.getStackVersion(), serviceName, componentName);
+          try {
+            componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+                stackId.getStackVersion(), serviceName, componentName);
+          } catch (ObjectNotFoundException e) {
+            // do nothing, componentId is checked for null later
+          }
         } else {
           for (String component : cluster.getService(serviceName).getServiceComponents().keySet()) {
             Map<String, ServiceComponentHost> componentHosts =

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index 8ffad0d..da7a9da 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@ -244,10 +244,10 @@ public class AmbariCustomCommandExecutionHelper {
 
     StackId stackId = cluster.getDesiredStackVersion();
     AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
-    ServiceInfo serviceInfo = ambariMetaInfo.getServiceInfo
-      (stackId.getStackName(), stackId.getStackVersion(), serviceName);
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo
-      (stackId.getStackName(), stackId.getStackVersion());
+    ServiceInfo serviceInfo = ambariMetaInfo.getService(
+        stackId.getStackName(), stackId.getStackVersion(), serviceName);
+    StackInfo stackInfo = ambariMetaInfo.getStack
+        (stackId.getStackName(), stackId.getStackVersion());
 
     CustomCommandDefinition customCommandDefinition = null;
     ComponentInfo ci = serviceInfo.getComponentByName(componentName);
@@ -473,10 +473,10 @@ public class AmbariCustomCommandExecutionHelper {
     StackId stackId = cluster.getDesiredStackVersion();
     AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
     ServiceInfo serviceInfo =
-        ambariMetaInfo.getServiceInfo(stackId.getStackName(),
+        ambariMetaInfo.getService(stackId.getStackName(),
             stackId.getStackVersion(), serviceName);
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
-      stackId.getStackVersion());
+    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),
+        stackId.getStackVersion());
 
 
     stage.addHostRoleExecutionCommand(hostname,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 196f3b0..7e95ac8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -326,7 +326,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           + " provided when creating a cluster");
     }
     StackId stackId = new StackId(request.getStackVersion());
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
+    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),
         stackId.getStackVersion());
     if (stackInfo == null) {
       throw new StackAccessException("stackName=" + stackId.getStackName() + ", stackVersion=" + stackId.getStackVersion());
@@ -566,7 +566,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
       StackId stackId = cluster.getCurrentStackVersion();
-      List<String> monitoringServices = ambariMetaInfo.getMonitoringServiceNames(
+      Collection<String> monitoringServices = ambariMetaInfo.getMonitoringServiceNames(
         stackId.getStackName(), stackId.getStackVersion());
 
       for (String serviceName : monitoringServices) {
@@ -1414,7 +1414,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         ServiceComponent sc = cluster.getService(serviceName).
           getServiceComponent(componentName);
         StackId stackId = sc.getDesiredStackVersion();
-        ComponentInfo compInfo = ambariMetaInfo.getComponentCategory(
+        ComponentInfo compInfo = ambariMetaInfo.getComponent(
           stackId.getStackName(), stackId.getStackVersion(), serviceName,
           componentName);
         if (runSmokeTest && compInfo.isMaster() &&
@@ -1546,13 +1546,13 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     String hostname = scHost.getHostName();
     String osFamily = clusters.getHost(hostname).getOsFamily();
     StackId stackId = cluster.getDesiredStackVersion();
-    ServiceInfo serviceInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
-      stackId.getStackVersion(), serviceName);
+    ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
+        stackId.getStackVersion(), serviceName);
     ComponentInfo componentInfo = ambariMetaInfo.getComponent(
       stackId.getStackName(), stackId.getStackVersion(),
       serviceName, componentName);
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
-      stackId.getStackVersion());
+    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),
+        stackId.getStackVersion());
 
     ExecutionCommand execCmd = stage.getExecutionCommandWrapper(scHost.getHostName(),
       scHost.getServiceComponentName()).getExecutionCommand();
@@ -1861,7 +1861,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                 break;
               case STARTED:
                 StackId stackId = scHost.getDesiredStackVersion();
-                ComponentInfo compInfo = ambariMetaInfo.getComponentCategory(
+                ComponentInfo compInfo = ambariMetaInfo.getComponent(
                     stackId.getStackName(), stackId.getStackVersion(), scHost.getServiceName(),
                     scHost.getServiceComponentName());
 
@@ -2939,7 +2939,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     StackId stackId = service.getDesiredStackVersion();
     ComponentInfo compInfo =
-        ambariMetaInfo.getServiceInfo(stackId.getStackName(),
+        ambariMetaInfo.getService(stackId.getStackName(),
             stackId.getStackVersion(), service.getName()).getClientComponent();
     if (compInfo != null) {
       try {
@@ -3128,13 +3128,14 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     String stackName = request.getStackName();
 
     if (stackName != null) {
-      org.apache.ambari.server.state.Stack stack = ambariMetaInfo.getStack(stackName);
-      response = Collections.singleton(stack.convertToResponse());
+      // this will throw an exception if the stack doesn't exist
+      ambariMetaInfo.getStacks(stackName);
+      response = Collections.singleton(new StackResponse(stackName));
     } else {
-      Set<org.apache.ambari.server.state.Stack> supportedStackNames = ambariMetaInfo.getStackNames();
+      Collection<StackInfo> supportedStacks = ambariMetaInfo.getStacks();
       response = new HashSet<StackResponse>();
-      for (org.apache.ambari.server.state.Stack stack: supportedStackNames) {
-        response.add(stack.convertToResponse());
+      for (StackInfo stack: supportedStacks) {
+        response.add(new StackResponse(stack.getName()));
       }
     }
     return response;
@@ -3145,9 +3146,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     try {
       ambariMetaInfo.init();
+    } catch (AmbariException e) {
+      throw e;
     } catch (Exception e) {
       throw new AmbariException(
-        "Ambari metainormation can't be read from the stack root directory");
+          "Ambari Meta Information can't be read from the stack root directory");
     }
 
     return null;
@@ -3312,13 +3315,17 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     String stackVersion = request.getStackVersion();
 
     if (stackVersion != null) {
-      StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackName, stackVersion);
+      StackInfo stackInfo = ambariMetaInfo.getStack(stackName, stackVersion);
       response = Collections.singleton(stackInfo.convertToResponse());
     } else {
-      Set<StackInfo> stackInfos = ambariMetaInfo.getStackInfos(stackName);
-      response = new HashSet<StackVersionResponse>();
-      for (StackInfo stackInfo: stackInfos) {
-        response.add(stackInfo.convertToResponse());
+      try {
+        Collection<StackInfo> stackInfos = ambariMetaInfo.getStacks(stackName);
+        response = new HashSet<StackVersionResponse>();
+        for (StackInfo stackInfo: stackInfos) {
+          response.add(stackInfo.convertToResponse());
+        }
+      } catch (StackAccessException e) {
+        response = Collections.emptySet();
       }
     }
 
@@ -3458,7 +3465,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     if (propertyName != null) {
       properties = ambariMetaInfo.getPropertiesByName(stackName, stackVersion, serviceName, propertyName);
     } else {
-      properties = ambariMetaInfo.getProperties(stackName, stackVersion, serviceName);
+      properties = ambariMetaInfo.getServiceProperties(stackName, stackVersion, serviceName);
     }
     for (PropertyInfo property: properties) {
       response.add(property.convertToResponse());

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
index a8e3451..2794c18 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 public class StackServiceResponse {
 
@@ -40,8 +39,6 @@ public class StackServiceResponse {
   private List<String> customCommands;
 
   private Map<String, Map<String, Map<String, String>>> configTypes;
-  private Set<String> excludedConfigTypes;
-
   private List<String> requiredServices;
 
   /**
@@ -56,8 +53,7 @@ public class StackServiceResponse {
     userName = null;
     comments = service.getComment();
     serviceVersion = service.getVersion();
-    configTypes = service.getConfigTypes();
-    excludedConfigTypes = service.getExcludedConfigTypes();
+    configTypes = service.getConfigTypeAttributes();
     requiredServices = service.getRequiredServices();
     serviceCheckSupported = null != service.getCommandScript();
 
@@ -132,10 +128,6 @@ public class StackServiceResponse {
   public Map<String, Map<String, Map<String, String>>> getConfigTypes() {
     return configTypes;
   }
-
-  public Set<String> getExcludedConfigTypes() {
-    return excludedConfigTypes;
-  }
   
   public List<String> getRequiredServices() {
     return requiredServices;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
index 2c25623..2c9179d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
@@ -300,11 +300,11 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
       throws SystemException, NoSuchResourceException, NoSuchParentResourceException {
     try {
       return command.invoke();
-    } catch (ObjectNotFoundException e) {
-      throw new NoSuchResourceException("The requested resource doesn't exist: " + e.getMessage(), e);
     } catch (ParentObjectNotFoundException e) {
       throw new NoSuchParentResourceException(e.getMessage(), e);
-    } catch (AmbariException e) {
+    } catch (ObjectNotFoundException e) {
+      throw new NoSuchResourceException("The requested resource doesn't exist: " + e.getMessage(), e);
+    }  catch (AmbariException e) {
       if (LOG.isErrorEnabled()) {
         LOG.error("Caught AmbariException when getting a resource", e);
       }
@@ -329,11 +329,11 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
       throws SystemException, NoSuchResourceException, NoSuchParentResourceException {
     try {
       return command.invoke();
-    } catch (ObjectNotFoundException e) {
-      throw new NoSuchResourceException("The specified resource doesn't exist: " + e.getMessage(), e);
     } catch (ParentObjectNotFoundException e) {
       throw new NoSuchParentResourceException(e.getMessage(), e);
-    } catch (AmbariException e) {
+    } catch (ObjectNotFoundException e) {
+      throw new NoSuchResourceException("The specified resource doesn't exist: " + e.getMessage(), e);
+    }  catch (AmbariException e) {
       if (LOG.isErrorEnabled()) {
         LOG.error("Caught AmbariException when modifying a resource", e);
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
index c49b677..4a1f596 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintResourceProvider.java
@@ -44,7 +44,6 @@ import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
 import org.apache.ambari.server.orm.entities.HostGroupEntity;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.ServiceInfo;
-import org.apache.ambari.server.state.PropertyInfo;
 
 import java.util.ArrayList;
 import java.util.Arrays;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java
index 5aca65b..d719805 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClientConfigResourceProvider.java
@@ -140,7 +140,7 @@ public class ClientConfigResourceProvider extends AbstractControllerResourceProv
       componentInfo = managementController.getAmbariMetaInfo().
               getComponent(stackId.getStackName(), stackId.getStackVersion(), serviceName, componentName);
       packageFolder = managementController.getAmbariMetaInfo().
-              getServiceInfo(stackId.getStackName(), stackId.getStackVersion(), serviceName).getServicePackageFolder();
+              getService(stackId.getStackName(), stackId.getStackVersion(), serviceName).getServicePackageFolder();
 
       String commandScript = componentInfo.getCommandScript().getScript();
       List<ClientConfigFileDefinition> clientConfigFiles = componentInfo.getClientConfigFiles();
@@ -216,7 +216,7 @@ public class ClientConfigResourceProvider extends AbstractControllerResourceProv
       ServiceInfo serviceInfo = null;
       String osFamily = null;
       clusterHostInfo = StageUtils.getClusterHostInfo(managementController.getClusters().getHostsForCluster(cluster.getClusterName()), cluster);
-      serviceInfo = managementController.getAmbariMetaInfo().getServiceInfo(stackId.getStackName(),
+      serviceInfo = managementController.getAmbariMetaInfo().getService(stackId.getStackName(),
               stackId.getStackVersion(), serviceName);
       clusterHostInfo = substituteHostIndexes(clusterHostInfo);
       osFamily = clusters.getHost(hostName).getOsFamily();

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index 96b4c8c..bb6a39c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -702,22 +702,13 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       BlueprintServiceConfigRequest blueprintConfigRequest =
         new BlueprintServiceConfigRequest(service);
 
-      Set<String> excludedConfigTypes = stack.getExcludedConfigurationTypes(service);
-      if (excludedConfigTypes == null) {
-        excludedConfigTypes = Collections.emptySet();
-      }
-
       for (String serviceConfigType : stack.getConfigurationTypes(service)) {
-        // skip config types that are considered excluded,
-        // which means that they typically belong to another service
-        if (!excludedConfigTypes.contains(serviceConfigType)) {
-          // skip handling of cluster-env here
-          if (!serviceConfigType.equals("cluster-env")) {
-            if (mapClusterConfigurations.containsKey(serviceConfigType)) {
-              blueprintConfigRequest.addConfigElement(serviceConfigType,
-                mapClusterConfigurations.get(serviceConfigType),
-                mapClusterAttributes.get(serviceConfigType));
-            }
+        // skip handling of cluster-env here
+        if (!serviceConfigType.equals("cluster-env")) {
+          if (mapClusterConfigurations.containsKey(serviceConfigType)) {
+            blueprintConfigRequest.addConfigElement(serviceConfigType,
+              mapClusterConfigurations.get(serviceConfigType),
+              mapClusterAttributes.get(serviceConfigType));
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index 9a2be41..20bd60d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -32,6 +32,7 @@ import org.apache.ambari.server.DuplicateResourceException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
 import org.apache.ambari.server.ServiceNotFoundException;
+import org.apache.ambari.server.StackAccessException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
@@ -427,8 +428,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   // Get the components for the given requests.
   protected Set<ServiceComponentResponse> getComponents(
       Set<ServiceComponentRequest> requests) throws AmbariException {
-    Set<ServiceComponentResponse> response =
-        new HashSet<ServiceComponentResponse>();
+
+    Set<ServiceComponentResponse> response = new HashSet<ServiceComponentResponse>();
     for (ServiceComponentRequest request : requests) {
       try {
         response.addAll(getComponents(request));
@@ -438,12 +439,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
           // there will be > 1 request in case of OR predicate
           throw e;
         }
-      } catch (ParentObjectNotFoundException ee) {
-        if (requests.size() == 1) {
-          throw ee;
-        }
       }
-      
     }
     return response;
   }
@@ -503,13 +499,15 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       ServiceComponent sc = s.getServiceComponent(request.getComponentName());
       ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
 
-      ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-          stackId.getStackVersion(), s.getName(), request.getComponentName());
-      if (componentInfo != null) {
+      try {
+        ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+            stackId.getStackVersion(), s.getName(), request.getComponentName());
         category = componentInfo.getCategory();
         if (category != null) {
           serviceComponentResponse.setCategory(category);
         }
+      } catch (ObjectNotFoundException e) {
+        // nothing to do, component doesn't exist
       }
 
       response.add(serviceComponentResponse);
@@ -549,17 +547,18 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
           continue;
         }
 
-        ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-            stackId.getStackVersion(), s.getName(), sc.getName());
         ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
-
-        String requestedCategory = request.getComponentCategory();
-        if (componentInfo != null) {
+        try {
+          ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+              stackId.getStackVersion(), s.getName(), sc.getName());
           category = componentInfo.getCategory();
           if (category != null) {
             serviceComponentResponse.setCategory(category);
           }
+        } catch (ObjectNotFoundException e) {
+          // component doesn't exist, nothing to do
         }
+        String requestedCategory = request.getComponentCategory();
         if (requestedCategory != null && !requestedCategory.isEmpty() &&
             category != null && !requestedCategory.equalsIgnoreCase(category)) {
           continue;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index 31c6c37..eb6237d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -848,7 +848,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
               + ", newDesiredState=" + newState;
           StackId sid = cluster.getDesiredStackVersion();
 
-          if ( ambariMetaInfo.getComponentCategory(
+          if ( ambariMetaInfo.getComponent(
               sid.getStackName(), sid.getStackVersion(), sc.getServiceName(),
               sch.getServiceComponentName()).isMaster()) {
             throw new AmbariException(error);
@@ -990,16 +990,16 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             boolean hasMM        = false;
 
             for (ServiceComponentHostResponse hostComponentResponse : hostComponentResponses ) {
-              ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-                  stackId.getStackVersion(), hostComponentResponse.getServiceName(),
-                  hostComponentResponse.getComponentName());
+              try {
+                ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+                    stackId.getStackVersion(), hostComponentResponse.getServiceName(),
+                    hostComponentResponse.getComponentName());
 
-              if (componentInfo != null) {
                 State state = getHostComponentState(hostComponentResponse);
                 // Components in MM should not affect service status,
                 // so we tend to ignore them
                 boolean isInMaintenance = ! MaintenanceState.OFF.toString().
-                        equals(hostComponentResponse.getMaintenanceState());
+                    equals(hostComponentResponse.getMaintenanceState());
 
                 if (state.equals(State.DISABLED)) {
                   hasDisabled = true;
@@ -1040,6 +1040,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
                     otherState = state;
                   }
                 }
+              } catch (ObjectNotFoundException e) {
+                // component doesn't exist, nothing to do
               }
             }
 
@@ -1086,13 +1088,12 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             State   nonStartedState     = null;
 
             for (ServiceComponentHostResponse hostComponentResponse : hostComponentResponses ) {
-              ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-                  stackId.getStackVersion(), hostComponentResponse.getServiceName(),
-                  hostComponentResponse.getComponentName());
+              try {
+                ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+                    stackId.getStackVersion(), hostComponentResponse.getServiceName(),
+                    hostComponentResponse.getComponentName());
 
-              if (componentInfo != null) {
                 if (componentInfo.isMaster()) {
-
                   String componentName = hostComponentResponse.getComponentName();
                   boolean isNameNode = false;
 
@@ -1118,6 +1119,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
                       nonStartedState = state;
                   }
                 }
+              } catch (ObjectNotFoundException e) {
+                // component doesn't exist, nothing to do
               }
             }
 
@@ -1162,13 +1165,12 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             State   nonStartedState        = null;
 
             for (ServiceComponentHostResponse hostComponentResponse : hostComponentResponses ) {
-              ComponentInfo componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
-                  stackId.getStackVersion(), hostComponentResponse.getServiceName(),
-                  hostComponentResponse.getComponentName());
+              try {
+                ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
+                    stackId.getStackVersion(), hostComponentResponse.getServiceName(),
+                    hostComponentResponse.getComponentName());
 
-              if (componentInfo != null) {
                 if (componentInfo.isMaster()) {
-
                   State state = getHostComponentState(hostComponentResponse);
 
                   switch (state) {
@@ -1183,6 +1185,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
                       nonStartedState = state;
                   }
                 }
+              } catch (ObjectNotFoundException e) {
+                // component doesn't exist, nothing to do
               }
             }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
index d6cfbd0..cd22340 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
@@ -100,13 +100,6 @@ class Stack {
       new HashMap<String, Map<String, Map<String, ConfigProperty>>>();
 
   /**
-   * Map of service to set of excluded config types
-   */
-  private Map<String, Set<String>> excludedConfigurationTypes =
-    new HashMap<String, Set<String>>();
-
-
-  /**
    * Ambari Management Controller, used to obtain Stack definitions
    */
   private final AmbariManagementController ambariManagementController;
@@ -161,7 +154,6 @@ class Stack {
     for (StackServiceResponse stackService : stackServices) {
       String serviceName = stackService.getServiceName();
       parseComponents(serviceName);
-      parseExcludedConfigurations(stackService);
       parseConfigurations(serviceName);
       registerConditionalDependencies();
     }
@@ -222,18 +214,6 @@ class Stack {
   }
 
   /**
-   * Get the set of excluded configuration types
-   *   for this service
-   *
-   * @param service service name
-   *
-   * @return Set of names of excluded config types
-   */
-  public Set<String> getExcludedConfigurationTypes(String service) {
-    return excludedConfigurationTypes.get(service);
-  }
-
-  /**
    * Get config properties for the specified service and configuration type.
    *
    * @param service  service name
@@ -412,15 +392,6 @@ class Stack {
   }
 
   /**
-   * Obtain the excluded configuration types from the StackServiceResponse
-   *
-   * @param stackServiceResponse the response object associated with this stack service
-   */
-  private void parseExcludedConfigurations(StackServiceResponse stackServiceResponse) {
-    excludedConfigurationTypes.put(stackServiceResponse.getServiceName(), stackServiceResponse.getExcludedConfigTypes());
-  }
-
-  /**
    * Parse configurations for the specified service from the stack definition.
    *
    * @param service  service name

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/metadata/RoleCommandOrder.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metadata/RoleCommandOrder.java b/ambari-server/src/main/java/org/apache/ambari/server/metadata/RoleCommandOrder.java
index 3427f9a..32668fa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metadata/RoleCommandOrder.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metadata/RoleCommandOrder.java
@@ -141,7 +141,7 @@ public class RoleCommandOrder {
     StackInfo stackInfo;
     String rcoFileLocation = null;
     try {
-      stackInfo = ambariMetaInfo.getStackInfo(stackName, stackVersion);
+      stackInfo = ambariMetaInfo.getStack(stackName, stackVersion);
       rcoFileLocation = stackInfo.getRcoFileLocation();
     } catch (AmbariException e) {
       LOG.warn("Error getting stack info for :" + stackName + "-" + stackVersion);

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
index 20ac03f..516dd2f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
@@ -22,6 +22,7 @@ import com.google.gson.Gson;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.ServiceInfo;
 
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
@@ -165,8 +166,8 @@ public class BlueprintEntity {
    * host group.  An operational configuration is achieved by overlaying host group configuration
    * on top of cluster configuration which overlays the default stack configurations.
    *
-   * @param stackInfo  stack information
-   * @param type       type of required property to check (PASSWORD|DEFAULT)
+   * @param stackInfo          stack information
+   * @param validatePasswords  whether password properties should be validated
    * @return map of required properties which are missing.  Empty map if none are missing.
    *
    * @throws IllegalArgumentException if blueprint contains invalid information
@@ -191,17 +192,17 @@ public class BlueprintEntity {
       for (HostGroupComponentEntity component : hostGroup.getComponents()) {
         //for now, AMBARI is not recognized as a service in Stacks
         if (! component.getName().equals("AMBARI_SERVER")) {
-          String service;
+          ServiceInfo service;
+          String serviceName;
           try {
-            service = stackInfo.getComponentToService(stackName, stackVersion, component.getName());
+            serviceName = stackInfo.getComponentToService(stackName, stackVersion, component.getName());
+            service = stackInfo.getService(stackName, stackVersion, serviceName);
           } catch (AmbariException e) {
             throw new IllegalArgumentException("Unable to determine the service associated with the" +
                 " component: " + component.getName());
           }
-          if (processedServices.add(service)) {
-            Map<String, PropertyInfo> serviceRequirements = stackInfo.getRequiredProperties(
-                stackName, stackVersion, service);
-
+          if (processedServices.add(serviceName)) {
+            Map<String, PropertyInfo> serviceRequirements = service.getRequiredProperties();
             for (PropertyInfo propertyInfo : serviceRequirements.values()) {
               if (! (validatePasswords ^ propertyInfo.getPropertyTypes().contains(PropertyInfo.PropertyType.PASSWORD))) {
                 String configCategory = propertyInfo.getFilename();

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
new file mode 100644
index 0000000..b27adea
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/BaseModule.java
@@ -0,0 +1,93 @@
+/**
+ * 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.stack;
+
+import org.apache.ambari.server.AmbariException;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Abstract base service definition module.
+ * Provides functionality that is common across multiple modules.
+ */
+public abstract class BaseModule<T, I> implements StackDefinitionModule<T, I> {
+  /**
+   * Merges child modules with the corresponding parent modules.
+   *
+   * @param allStacks      collection of all stack module in stack definition
+   * @param modules        child modules of this module that are to be merged
+   * @param parentModules  parent modules which the modules are to be merged with
+   *
+   * @return collection of the merged modules
+   */
+  protected <T extends StackDefinitionModule<T, ?>> Collection<T> mergeChildModules(
+      Map<String, StackModule> allStacks, Map<String, T> modules, Map<String, T> parentModules)
+        throws AmbariException {
+
+    Set<String> addedModules = new HashSet<String>();
+    Collection<T> mergedModules = new HashSet<T>();
+
+    for (T module : modules.values()) {
+      String id = module.getId();
+      addedModules.add(id);
+      if (! module.isDeleted()) {
+        if (parentModules.containsKey(id)) {
+          module.resolve(parentModules.get(id), allStacks);
+        }
+        mergedModules.add(module);
+      }
+    }
+
+    // add non-overlapping parent modules
+    for (T parentModule : parentModules.values()) {
+      String id = parentModule.getId();
+      if (! addedModules.contains(id)) {
+        mergedModules.add(parentModule);
+      }
+    }
+    return mergedModules;
+  }
+
+  /**
+   * Finalize a modules child components.
+   * Any child module marked as deleted will be removed from this module after finalizing
+   * the child.
+   *
+   * @param modules  child modules to finalize
+   */
+  protected void finalizeChildModules(Collection<? extends StackDefinitionModule> modules) {
+    Iterator<? extends StackDefinitionModule> iter = modules.iterator();
+    while (iter.hasNext()) {
+      StackDefinitionModule module = iter.next();
+      module.finalizeModule();
+      if (module.isDeleted()) {
+        iter.remove();
+      }
+    }
+  }
+
+  @Override
+  public void finalizeModule() {
+    // do nothing by default
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2fc7adec/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
new file mode 100644
index 0000000..0f2a691
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ComponentModule.java
@@ -0,0 +1,150 @@
+/**
+ * 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.stack;
+
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.CustomCommandDefinition;
+import org.apache.ambari.server.state.DependencyInfo;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Component module which provides all functionality related to parsing and fully
+ * resolving service components from the stack definition.
+ */
+public class ComponentModule extends BaseModule<ComponentModule, ComponentInfo> {
+  /**
+   * Corresponding component info
+   */
+  private ComponentInfo componentInfo;
+
+  /**
+   * Constructor.
+   *
+   * @param componentInfo  associated component info
+   */
+  public ComponentModule(ComponentInfo componentInfo) {
+    this.componentInfo = componentInfo;
+  }
+
+  @Override
+  public void resolve(ComponentModule parent, Map<String, StackModule> allStacks) {
+    ComponentInfo parentInfo = parent.getModuleInfo();
+
+    if (componentInfo.getCommandScript() == null) {
+      componentInfo.setCommandScript(parentInfo.getCommandScript());
+    }
+    if (componentInfo.getDisplayName() == null) {
+      componentInfo.setDisplayName(parentInfo.getDisplayName());
+    }
+    if (componentInfo.getConfigDependencies() == null) {
+      componentInfo.setConfigDependencies(parentInfo.getConfigDependencies());
+    }
+    if (componentInfo.getClientConfigFiles() == null) {
+      componentInfo.setClientConfigFiles(parentInfo.getClientConfigFiles());
+    }
+    if (componentInfo.getClientsToUpdateConfigs() == null) {
+      componentInfo.setClientsToUpdateConfigs(parentInfo.getClientsToUpdateConfigs());
+    }
+    if (componentInfo.getCategory() == null) {
+      componentInfo.setCategory(parentInfo.getCategory());
+    }
+    if (componentInfo.getCardinality() == null) {
+      componentInfo.setCardinality(parentInfo.getCardinality());
+    }
+    if (componentInfo.getAutoDeploy() == null) {
+      componentInfo.setAutoDeploy(parentInfo.getAutoDeploy());
+    }
+
+    mergeComponentDependencies(parentInfo.getDependencies(),
+        componentInfo.getDependencies());
+
+    mergeCustomCommands(parentInfo.getCustomCommands(),
+        componentInfo.getCustomCommands());
+  }
+
+  @Override
+  public ComponentInfo getModuleInfo() {
+    return componentInfo;
+  }
+
+  @Override
+  public boolean isDeleted() {
+    return componentInfo.isDeleted();
+  }
+
+  @Override
+  public String getId() {
+    return componentInfo.getName();
+  }
+
+  /**
+   * Merge component dependencies.
+   * Child dependencies override a parent dependency of the same name.
+   *
+   * @param parentDependencies  parent dependencies
+   * @param childDependencies   child dependencies
+   */
+  //todo: currently there is no way to remove an inherited dependency
+  private void mergeComponentDependencies(List<DependencyInfo> parentDependencies,
+                                          List<DependencyInfo> childDependencies) {
+
+    Collection<String> existingNames = new HashSet<String>();
+
+    for (DependencyInfo childDependency : childDependencies) {
+      existingNames.add(childDependency.getName());
+    }
+    if (parentDependencies != null) {
+      for (DependencyInfo parentDependency : parentDependencies) {
+        if (! existingNames.contains(parentDependency.getName())) {
+          childDependencies.add(parentDependency);
+        }
+      }
+    }
+  }
+
+  /**
+   * Merge custom commands.
+   * Child commands override a parent command of the same name.
+   *
+   * @param parentCommands  parent commands
+   * @param childCommands   child commands
+   */
+  //todo: duplicated in ServiceModule
+  //todo: currently there is no way to remove an inherited custom command
+  private void mergeCustomCommands(List<CustomCommandDefinition> parentCommands,
+                                   List<CustomCommandDefinition> childCommands) {
+
+    Collection<String> existingNames = new HashSet<String>();
+
+    for (CustomCommandDefinition childCmd : childCommands) {
+      existingNames.add(childCmd.getName());
+    }
+    if (parentCommands != null) {
+      for (CustomCommandDefinition parentCmd : parentCommands) {
+        if (! existingNames.contains(parentCmd.getName())) {
+          childCommands.add(parentCmd);
+        }
+      }
+    }
+  }
+}