/** * 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.controller.internal; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.DuplicateResourceException; import org.apache.ambari.server.StaticallyInject; import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; import org.apache.ambari.server.controller.spi.NoSuchResourceException; import org.apache.ambari.server.controller.spi.Predicate; import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.controller.spi.RequestStatus; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException; import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.apache.ambari.server.orm.dao.SettingDAO; import org.apache.ambari.server.orm.entities.SettingEntity; import org.apache.ambari.server.security.authorization.AuthorizationException; import org.apache.ambari.server.security.authorization.AuthorizationHelper; import org.apache.ambari.server.security.authorization.RoleAuthorization; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import com.google.inject.Inject; /** * This class deals with managing CRUD operation on {@link SettingEntity}. */ @StaticallyInject public class SettingResourceProvider extends AbstractAuthorizedResourceProvider { private static final String SETTINGS = "Settings"; protected static final String ID = "id"; protected static final String SETTING = "Setting"; protected static final String SETTING_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(SETTINGS, "name"); protected static final String SETTING_SETTING_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId(SETTINGS, "setting_type"); protected static final String SETTING_CONTENT_PROPERTY_ID = PropertyHelper.getPropertyId(SETTINGS, "content"); protected static final String SETTING_UPDATED_BY_PROPERTY_ID = PropertyHelper.getPropertyId(SETTINGS, "updated_by"); protected static final String SETTING_UPDATE_TIMESTAMP_PROPERTY_ID = PropertyHelper.getPropertyId(SETTINGS, "update_timestamp"); /** * The property ids for setting resource. */ private static final Set<String> propertyIds = new HashSet<>(); /** * The key property ids for setting resource. */ private static final Map<Resource.Type, String> keyPropertyIds = new HashMap<>(); private static final Set<String> requiredProperties = new HashSet<>(); @Inject private static SettingDAO dao; static { propertyIds.add(SETTING_NAME_PROPERTY_ID); propertyIds.add(SETTING_SETTING_TYPE_PROPERTY_ID); propertyIds.add(SETTING_CONTENT_PROPERTY_ID); propertyIds.add(SETTING_UPDATED_BY_PROPERTY_ID); propertyIds.add(SETTING_UPDATE_TIMESTAMP_PROPERTY_ID); propertyIds.add(SETTING_SETTING_TYPE_PROPERTY_ID); propertyIds.add(SETTING); keyPropertyIds.put(Resource.Type.Setting, SETTING_NAME_PROPERTY_ID); requiredProperties.add(SETTING_NAME_PROPERTY_ID); requiredProperties.add(SETTING_SETTING_TYPE_PROPERTY_ID); requiredProperties.add(SETTING_CONTENT_PROPERTY_ID); } protected SettingResourceProvider() { super(propertyIds, keyPropertyIds); EnumSet<RoleAuthorization> requiredAuthorizations = EnumSet.of(RoleAuthorization.AMBARI_MANAGE_SETTINGS); setRequiredCreateAuthorizations(requiredAuthorizations); setRequiredDeleteAuthorizations(requiredAuthorizations); setRequiredUpdateAuthorizations(requiredAuthorizations); } @Override protected Set<String> getPKPropertyIds() { return new HashSet<>(keyPropertyIds.values()); } @Override public RequestStatus createResourcesAuthorized(Request request) throws NoSuchParentResourceException, ResourceAlreadyExistsException, SystemException { Set<Resource> associatedResources = new HashSet<>(); for (Map<String, Object> properties : request.getProperties()) { SettingEntity settingEntity = createResources(newCreateCommand(request, properties)); Resource resource = new ResourceImpl(Resource.Type.Setting); resource.setProperty(SETTING_NAME_PROPERTY_ID, settingEntity.getName()); associatedResources.add(resource); } return getRequestStatus(null, associatedResources); } @Override public Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws NoSuchResourceException { List<SettingEntity> entities = new LinkedList<>(); final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate); if (propertyMaps.isEmpty()) { entities = dao.findAll(); } for (Map<String, Object> propertyMap: propertyMaps) { if (propertyMap.containsKey(SETTING_NAME_PROPERTY_ID)) { String name = propertyMap.get(SETTING_NAME_PROPERTY_ID).toString(); SettingEntity entity = dao.findByName(name); if (entity == null) { throw new NoSuchResourceException(String.format("Setting with name %s does not exists", name)); } entities.add(entity); } else { entities = dao.findAll(); break; } } Set<String> requestedIds = getRequestPropertyIds(request, predicate); Set<Resource> resources = new HashSet<>(); for(SettingEntity entity : entities) { resources.add(toResource(entity, requestedIds)); } return resources; } @Override public RequestStatus updateResourcesAuthorized(Request request, Predicate predicate) throws NoSuchResourceException, NoSuchParentResourceException, SystemException { modifyResources(newUpdateCommand(request)); return getRequestStatus(null); } @Override public RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) { final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate); for (Map<String, Object> propertyMap : propertyMaps) { if (propertyMap.containsKey(SETTING_NAME_PROPERTY_ID)) { dao.removeByName(propertyMap.get(SETTING_NAME_PROPERTY_ID).toString()); } } return getRequestStatus(null); } private Command<SettingEntity> newCreateCommand(final Request request, final Map<String, Object> properties) { return new Command<SettingEntity>() { @Override public SettingEntity invoke() throws AmbariException, AuthorizationException { SettingEntity entity = toEntity(properties); if (dao.findByName(entity.getName()) != null) { throw new DuplicateResourceException( String.format("Setting already exists. setting name :%s ", entity.getName())); } dao.create(entity); notifyCreate(Resource.Type.Setting, request); return entity; } }; } private Command<Void> newUpdateCommand(final Request request) throws NoSuchResourceException, SystemException { return new Command<Void>() { @Override public Void invoke() throws AmbariException { final Set<Map<String, Object>> propertyMaps = request.getProperties(); for (Map<String, Object> propertyMap : propertyMaps) { if (propertyMap.containsKey(SETTING_NAME_PROPERTY_ID)) { String name = propertyMap.get(SETTING_NAME_PROPERTY_ID).toString(); SettingEntity entity = dao.findByName(name); if (entity == null) { throw new AmbariException(String.format("There is no setting with name: %s ", name)); } updateEntity(entity, propertyMap); dao.merge(entity); } } return null; } }; } private void updateEntity(SettingEntity entity, Map<String, Object> propertyMap) throws AmbariException { String name = propertyMap.get(SETTING_NAME_PROPERTY_ID).toString(); if (!Objects.equals(name, entity.getName())) { throw new AmbariException("Name for Setting is immutable, cannot change name."); } if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(SETTING_CONTENT_PROPERTY_ID)))) { entity.setContent(propertyMap.get(SETTING_CONTENT_PROPERTY_ID).toString()); } if (StringUtils.isNotBlank(ObjectUtils.toString(propertyMap.get(SETTING_SETTING_TYPE_PROPERTY_ID)))) { entity.setSettingType(propertyMap.get(SETTING_SETTING_TYPE_PROPERTY_ID).toString()); } entity.setUpdatedBy(AuthorizationHelper.getAuthenticatedName()); entity.setUpdateTimestamp(System.currentTimeMillis()); } private Resource toResource(final SettingEntity settingEntity, final Set<String> requestedIds) { Resource resource = new ResourceImpl(Resource.Type.Setting); setResourceProperty(resource, SETTING_NAME_PROPERTY_ID, settingEntity.getName(), requestedIds); setResourceProperty(resource, SETTING_SETTING_TYPE_PROPERTY_ID, settingEntity.getSettingType(), requestedIds); setResourceProperty(resource, SETTING_CONTENT_PROPERTY_ID, settingEntity.getContent(), requestedIds); setResourceProperty(resource, SETTING_UPDATED_BY_PROPERTY_ID, settingEntity.getUpdatedBy(), requestedIds); setResourceProperty(resource, SETTING_UPDATE_TIMESTAMP_PROPERTY_ID, settingEntity.getUpdateTimestamp(), requestedIds); return resource; } private SettingEntity toEntity(final Map<String, Object> properties) throws AmbariException { for (String propertyName: requiredProperties) { if (properties.get(propertyName) == null) { throw new AmbariException(String.format("Property %s should be provided", propertyName)); } } SettingEntity entity = new SettingEntity(); entity.setName(properties.get(SETTING_NAME_PROPERTY_ID).toString()); entity.setSettingType(properties.get(SETTING_SETTING_TYPE_PROPERTY_ID).toString()); entity.setContent(properties.get(SETTING_CONTENT_PROPERTY_ID).toString()); entity.setUpdatedBy(AuthorizationHelper.getAuthenticatedName()); entity.setUpdateTimestamp(System.currentTimeMillis()); return entity; } }