| /** |
| * 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 org.apache.ambari.server.state.LogDefinition; |
| import org.apache.commons.lang.builder.ToStringBuilder; |
| import org.apache.commons.lang.builder.ToStringStyle; |
| |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * 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> implements Validable { |
| /** |
| * Corresponding component info |
| */ |
| private ComponentInfo componentInfo; |
| |
| /** |
| * validity flag |
| */ |
| protected boolean valid = true; |
| |
| private Set<String> errorSet = new HashSet<String>(); |
| |
| /** |
| * Constructor. |
| * |
| * @param componentInfo associated component info |
| */ |
| public ComponentModule(ComponentInfo componentInfo) { |
| this.componentInfo = componentInfo; |
| } |
| |
| @Override |
| public void resolve(ComponentModule parent, Map<String, StackModule> allStacks, |
| Map<String, ServiceModule> commonServices, Map<String, ExtensionModule> extensions) { |
| if (parent != null) { |
| ComponentInfo parentInfo = parent.getModuleInfo(); |
| if (!parent.isValid()) { |
| setValid(false); |
| addErrors(parent.getErrors()); |
| } |
| |
| 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()); |
| } |
| |
| // Inherit versionAdvertised from the parent if the current Component Info has it as null or "inherit". |
| if (null == componentInfo.getVersionAdvertisedField()) { |
| componentInfo.setVersionAdvertised(parentInfo.isVersionAdvertised()); |
| } else { |
| // Set to explicit boolean |
| componentInfo.setVersionAdvertised(componentInfo.getVersionAdvertisedField().booleanValue()); |
| } |
| |
| if (componentInfo.getDecommissionAllowed() == null) { |
| componentInfo.setDecommissionAllowed(parentInfo.getDecommissionAllowed()); |
| } |
| |
| if (componentInfo.getAutoDeploy() == null) { |
| componentInfo.setAutoDeploy(parentInfo.getAutoDeploy()); |
| } |
| |
| componentInfo.setRecoveryEnabled(parentInfo.isRecoveryEnabled()); |
| |
| if (componentInfo.getBulkCommandDefinition() == null){ |
| componentInfo.setBulkCommands(parentInfo.getBulkCommandDefinition()); |
| } |
| |
| if (componentInfo.getReassignAllowed() == null) { |
| componentInfo.setReassignAllowed(parentInfo.getReassignAllowed()); |
| } |
| |
| mergeComponentDependencies(parentInfo.getDependencies(), |
| componentInfo.getDependencies()); |
| |
| mergeCustomCommands(parentInfo.getCustomCommands(), |
| componentInfo.getCustomCommands()); |
| |
| mergeLogs(parentInfo.getLogs(), componentInfo.getLogs()); |
| } |
| } |
| |
| @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); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Merge logs. |
| * Child logs override a parent log of the same log id. |
| * |
| * @param parentLogs parent logs |
| * @param childLogs child logs |
| */ |
| //todo: currently there is no way to remove an inherited log |
| private void mergeLogs(List<LogDefinition> parentLogs, List<LogDefinition> childLogs) { |
| Collection<String> existingLogIds = new HashSet<String>(); |
| |
| for (LogDefinition childLog : childLogs) { |
| existingLogIds.add(childLog.getLogId()); |
| } |
| if (parentLogs != null) { |
| for (LogDefinition parentLog : parentLogs) { |
| if (! existingLogIds.contains(parentLog.getLogId())) { |
| childLogs.add(parentLog); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public boolean isValid() { |
| return valid; |
| } |
| |
| @Override |
| public void setValid(boolean valid) { |
| this.valid = valid; |
| } |
| |
| @Override |
| public void addError(String error) { |
| errorSet.add(error); |
| } |
| |
| @Override |
| public Collection<String> getErrors() { |
| return errorSet; |
| } |
| |
| @Override |
| public void addErrors(Collection<String> errors) { |
| this.errorSet.addAll(errors); |
| } |
| |
| @Override |
| public String toString() { |
| return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); |
| } |
| } |