/* * Copyright 2014-2016 CyberVision, Inc. * * Licensed 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.kaaproject.kaa.server.control.service; import static org.apache.commons.lang.StringUtils.isNotBlank; import static org.kaaproject.kaa.server.admin.shared.util.Utils.isEmpty; import org.apache.avro.Schema; import org.apache.commons.codec.binary.Base64; import org.apache.thrift.TException; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.kaaproject.avro.ui.shared.Fqn; import org.kaaproject.kaa.common.avro.GenericAvroConverter; import org.kaaproject.kaa.common.dto.AbstractSchemaDto; import org.kaaproject.kaa.common.dto.ApplicationDto; import org.kaaproject.kaa.common.dto.ChangeConfigurationNotification; import org.kaaproject.kaa.common.dto.ChangeNotificationDto; import org.kaaproject.kaa.common.dto.ChangeProfileFilterNotification; import org.kaaproject.kaa.common.dto.ChangeType; import org.kaaproject.kaa.common.dto.ConfigurationDto; import org.kaaproject.kaa.common.dto.ConfigurationRecordDto; import org.kaaproject.kaa.common.dto.ConfigurationSchemaDto; import org.kaaproject.kaa.common.dto.EndpointGroupDto; import org.kaaproject.kaa.common.dto.EndpointNotificationDto; import org.kaaproject.kaa.common.dto.EndpointProfileBodyDto; import org.kaaproject.kaa.common.dto.EndpointProfileDto; import org.kaaproject.kaa.common.dto.EndpointProfileSchemaDto; import org.kaaproject.kaa.common.dto.EndpointProfilesBodyDto; import org.kaaproject.kaa.common.dto.EndpointProfilesPageDto; import org.kaaproject.kaa.common.dto.EndpointSpecificConfigurationDto; import org.kaaproject.kaa.common.dto.EndpointUserConfigurationDto; import org.kaaproject.kaa.common.dto.EndpointUserDto; import org.kaaproject.kaa.common.dto.HasId; import org.kaaproject.kaa.common.dto.NotificationDto; import org.kaaproject.kaa.common.dto.NotificationSchemaDto; import org.kaaproject.kaa.common.dto.NotificationTypeDto; import org.kaaproject.kaa.common.dto.PageLinkDto; import org.kaaproject.kaa.common.dto.ProfileFilterDto; import org.kaaproject.kaa.common.dto.ProfileFilterRecordDto; import org.kaaproject.kaa.common.dto.ProfileVersionPairDto; import org.kaaproject.kaa.common.dto.ServerProfileSchemaDto; import org.kaaproject.kaa.common.dto.TenantDto; import org.kaaproject.kaa.common.dto.TopicDto; import org.kaaproject.kaa.common.dto.UpdateNotificationDto; import org.kaaproject.kaa.common.dto.UserDto; import org.kaaproject.kaa.common.dto.VersionDto; import org.kaaproject.kaa.common.dto.admin.RecordKey; import org.kaaproject.kaa.common.dto.admin.RecordKey.RecordFiles; import org.kaaproject.kaa.common.dto.admin.SdkPlatform; import org.kaaproject.kaa.common.dto.admin.SdkProfileDto; import org.kaaproject.kaa.common.dto.credentials.CredentialsDto; import org.kaaproject.kaa.common.dto.credentials.CredentialsStatus; import org.kaaproject.kaa.common.dto.credentials.EndpointRegistrationDto; import org.kaaproject.kaa.common.dto.ctl.CTLSchemaDto; import org.kaaproject.kaa.common.dto.ctl.CtlSchemaMetaInfoDto; import org.kaaproject.kaa.common.dto.event.AefMapInfoDto; import org.kaaproject.kaa.common.dto.event.ApplicationEventFamilyMapDto; import org.kaaproject.kaa.common.dto.event.EcfInfoDto; import org.kaaproject.kaa.common.dto.event.EventClassDto; import org.kaaproject.kaa.common.dto.event.EventClassFamilyDto; import org.kaaproject.kaa.common.dto.event.EventClassFamilyVersionDto; import org.kaaproject.kaa.common.dto.event.EventClassType; import org.kaaproject.kaa.common.dto.file.FileData; import org.kaaproject.kaa.common.dto.logs.LogAppenderDto; import org.kaaproject.kaa.common.dto.logs.LogSchemaDto; import org.kaaproject.kaa.common.dto.user.UserVerifierDto; import org.kaaproject.kaa.common.hash.EndpointObjectHash; import org.kaaproject.kaa.server.admin.services.util.Utils; import org.kaaproject.kaa.server.admin.shared.services.KaaAdminServiceException; import org.kaaproject.kaa.server.admin.shared.services.ServiceErrorCode; import org.kaaproject.kaa.server.common.Base64Util; import org.kaaproject.kaa.server.common.Version; import org.kaaproject.kaa.server.common.core.algorithms.AvroUtils; import org.kaaproject.kaa.server.common.core.schema.DataSchema; import org.kaaproject.kaa.server.common.core.schema.ProtocolSchema; import org.kaaproject.kaa.server.common.dao.ApplicationEventMapService; import org.kaaproject.kaa.server.common.dao.ApplicationService; import org.kaaproject.kaa.server.common.dao.ConfigurationService; import org.kaaproject.kaa.server.common.dao.CtlService; import org.kaaproject.kaa.server.common.dao.EndpointRegistrationService; import org.kaaproject.kaa.server.common.dao.EndpointService; import org.kaaproject.kaa.server.common.dao.EndpointSpecificConfigurationService; import org.kaaproject.kaa.server.common.dao.EventClassService; import org.kaaproject.kaa.server.common.dao.LogAppendersService; import org.kaaproject.kaa.server.common.dao.LogSchemaService; import org.kaaproject.kaa.server.common.dao.NotificationService; import org.kaaproject.kaa.server.common.dao.ProfileService; import org.kaaproject.kaa.server.common.dao.SdkProfileService; import org.kaaproject.kaa.server.common.dao.ServerProfileService; import org.kaaproject.kaa.server.common.dao.TopicService; import org.kaaproject.kaa.server.common.dao.UserConfigurationService; import org.kaaproject.kaa.server.common.dao.UserService; import org.kaaproject.kaa.server.common.dao.UserVerifierService; import org.kaaproject.kaa.server.common.dao.exception.CredentialsServiceException; import org.kaaproject.kaa.server.common.dao.exception.EndpointRegistrationServiceException; import org.kaaproject.kaa.server.common.dao.exception.IncorrectParameterException; import org.kaaproject.kaa.server.common.dao.exception.NotFoundException; import org.kaaproject.kaa.server.common.log.shared.RecordWrapperSchemaGenerator; import org.kaaproject.kaa.server.common.thrift.KaaThriftService; import org.kaaproject.kaa.server.common.thrift.gen.operations.Notification; import org.kaaproject.kaa.server.common.thrift.gen.operations.Operation; import org.kaaproject.kaa.server.common.thrift.gen.operations.OperationsThriftService.Iface; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftActorClassifier; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftClusterEntityType; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointConfigurationRefreshMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointDeregistrationMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEntityAddress; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftServerProfileUpdateMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftUnicastNotificationMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.UserConfigurationUpdate; import org.kaaproject.kaa.server.common.zk.control.ControlNode; import org.kaaproject.kaa.server.common.zk.gen.OperationsNodeInfo; import org.kaaproject.kaa.server.common.zk.gen.TransportMetaData; import org.kaaproject.kaa.server.common.zk.gen.VersionConnectionInfoPair; import org.kaaproject.kaa.server.common.zk.operations.OperationsNodeListener; import org.kaaproject.kaa.server.control.service.exception.ControlServiceException; import org.kaaproject.kaa.server.control.service.schema.SchemaLibraryGenerator; import org.kaaproject.kaa.server.control.service.sdk.SdkGenerator; import org.kaaproject.kaa.server.control.service.sdk.SdkGeneratorFactory; import org.kaaproject.kaa.server.control.service.sdk.event.EventFamilyMetadata; import org.kaaproject.kaa.server.control.service.zk.ControlZkService; import org.kaaproject.kaa.server.hash.ConsistentHashResolver; import org.kaaproject.kaa.server.node.service.credentials.CredentialsServiceLocator; import org.kaaproject.kaa.server.node.service.credentials.CredentialsServiceRegistry; import org.kaaproject.kaa.server.node.service.thrift.OperationsServiceMsg; import org.kaaproject.kaa.server.operations.pojo.exceptions.GetDeltaException; import org.kaaproject.kaa.server.operations.service.delta.DeltaService; import org.kaaproject.kaa.server.resolve.OperationsServerResolver; import org.kaaproject.kaa.server.thrift.NeighborTemplate; import org.kaaproject.kaa.server.thrift.Neighbors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.helpers.MessageFormatter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.Base64Utils; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import javax.annotation.PreDestroy; /** * The Class DefaultControlService. */ @Service public class DefaultControlService implements ControlService { /** * The Constant DEFAULT_NEIGHBOR_CONNECTIONS_SIZE. */ private static final int DEFAULT_NEIGHBOR_CONNECTIONS_SIZE = 10; /** * The Constant DEFAULT_USER_HASH_PARTITIONS_SIZE. */ private static final int DEFAULT_USER_HASH_PARTITIONS_SIZE = 10; /** * The Constant LOG. */ private static final Logger LOG = LoggerFactory.getLogger(DefaultControlService.class); /** * The Constant SCHEMA_NAME_PATTERN. */ private static final String SCHEMA_NAME_PATTERN = "kaa-record-schema-l{}.avsc"; /** * The Constant DATA_NAME_PATTERN. */ private static final String DATA_NAME_PATTERN = "kaa-{}-schema-v{}.avsc"; /** * The Constant LOG_SCHEMA_LIBRARY_NAME_PATTERN. */ private static final String LOG_SCHEMA_LIBRARY_NAME_PATTERN = "kaa-record-lib-l{}"; /** * A template for naming exported CTL library schemas. * * @see #exportCtlSchemaFlatAsLibrary(CTLSchemaDto) */ private static final String CTL_LIBRARY_EXPORT_TEMPLATE = "{0}.v{1}"; @Autowired private DeltaService deltaService; @Autowired private UserService userService; @Autowired private ApplicationService applicationService; @Autowired private ConfigurationService configurationService; @Autowired private UserConfigurationService userConfigurationService; /** * The profile service. */ @Autowired private ProfileService profileService; /** * The server profile service. */ @Autowired private ServerProfileService serverProfileService; /** * The endpoint service. */ @Autowired private EndpointService endpointService; /** * The notification service. */ @Autowired private NotificationService notificationService; /** * The topic service. */ @Autowired private TopicService topicService; /** * The event class service. */ @Autowired private EventClassService eventClassService; /** * The application event map service. */ @Autowired private ApplicationEventMapService applicationEventMapService; /** * The control zk service. */ @Autowired private ControlZkService controlZkService; /** * The log schema service. */ @Autowired private LogSchemaService logSchemaService; /** * The log appender service. */ @Autowired private LogAppendersService logAppenderService; /** * The user verifier service. */ @Autowired private UserVerifierService userVerifierService; /** * The sdk key service. */ @Autowired private SdkProfileService sdkProfileService; @Autowired private CtlService ctlService; @Autowired @Qualifier("rootCredentialsServiceLocator") private CredentialsServiceLocator credentialsServiceLocator; @Autowired private CredentialsServiceRegistry credentialsServiceRegistry; @Autowired private EndpointRegistrationService endpointRegistrationService; @Autowired private EndpointSpecificConfigurationService endpointSpecificConfigurationService; /** * The neighbor connections size. */ @Value("#{properties[max_number_neighbor_connections]}") private int neighborConnectionsSize = DEFAULT_NEIGHBOR_CONNECTIONS_SIZE; /** * The user hash partitions. */ @Value("#{properties[user_hash_partitions]}") private int userHashPartitions = DEFAULT_USER_HASH_PARTITIONS_SIZE; /** * The neighbors. */ private volatile Neighbors <NeighborTemplate<OperationsServiceMsg>, OperationsServiceMsg> neighbors; /** * The resolver. */ private volatile OperationsServerResolver resolver; /** * The zk lock. */ private Object zkLock = new Object(); /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getTenants() */ @Override public List<TenantDto> getTenants() throws ControlServiceException { return userService.findAllTenants(); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getTenant(java * .lang.String) */ @Override public TenantDto getTenant(String tenantId) throws ControlServiceException { return userService.findTenantById(tenantId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editTenant(org * .kaaproject.kaa.common.dto.TenantDto) */ @Override public TenantDto editTenant(TenantDto tenant) throws ControlServiceException { return userService.saveTenant(tenant); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#deleteTenant * (java.lang.String) */ @Override public void deleteTenant(String tenantId) throws ControlServiceException { userService.removeTenantById(tenantId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService#getUsers() */ @Override public List<UserDto> getUsers() throws ControlServiceException { return userService.findAllUsers(); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getTenantUsers * (java.lang.String) */ @Override public List<UserDto> getTenantUsers(String tenantId) throws ControlServiceException { return userService.findAllTenantUsers(tenantId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getUser(java * .lang.String) */ @Override public UserDto getUser(String userId) throws ControlServiceException { return userService.findUserById(userId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getUserByExternalUid (java.lang.String) */ @Override public UserDto getUserByExternalUid(String uid) throws ControlServiceException { return userService.findUserByExternalUid(uid); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editUser(org * .kaaproject.kaa.common.dto.UserDto) */ @Override public UserDto editUser(UserDto user) throws ControlServiceException { return userService.saveUser(user); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#deleteUser(java * .lang.String) */ @Override public void deleteUser(String userId) throws ControlServiceException { userService.removeUserById(userId); } @Override public List<UserDto> findAllTenantAdminsByTenantId(String tenantId) throws ControlServiceException { return userService.findAllTenantAdminsByTenantId(tenantId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getApplication * (java.lang.String) */ @Override public ApplicationDto getApplication(String applicationId) throws ControlServiceException { return applicationService.findAppById(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getApplicationByApplicationToken(java.lang.String) */ @Override public ApplicationDto getApplicationByApplicationToken(String applicationToken) throws ControlServiceException { return applicationService.findAppByApplicationToken(applicationToken); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getApplicationsByTenantId(java.lang.String) */ @Override public List<ApplicationDto> getApplicationsByTenantId(String tenantId) throws ControlServiceException { return applicationService.findAppsByTenantId(tenantId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editApplication * (org.kaaproject.kaa.common.dto.ApplicationDto) */ @Override public ApplicationDto editApplication(ApplicationDto application) throws ControlServiceException { ApplicationDto storedApplication = applicationService .findAppByApplicationToken(application.getApplicationToken()); if (storedApplication != null) { application.setId(storedApplication.getId()); } boolean update = !isEmpty(application.getId()); ApplicationDto appDto = applicationService.saveApp(application); if (update) { LOG.info("[{}] Broadcasting notification about application {} update.", application.getId(), application.getApplicationToken()); Notification thriftNotification = new Notification(); thriftNotification.setAppId(appDto.getId()); thriftNotification.setAppSeqNumber(appDto.getSequenceNumber()); thriftNotification.setOp(Operation.APP_UPDATE); controlZkService.sendEndpointNotification(thriftNotification); } return appDto; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteApplication (java.lang.String) */ @Override public void deleteApplication(String applicationId) throws ControlServiceException { applicationService.removeAppById(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getConfigurationSchemasByApplicationId(java.lang.String) */ @Override public List<ConfigurationSchemaDto> getConfigurationSchemasByApplicationId( String applicationId) throws ControlServiceException { return configurationService.findConfSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getConfigurationSchema(java.lang.String) */ @Override public ConfigurationSchemaDto getConfigurationSchema( String configurationSchemaId) throws ControlServiceException { return configurationService.findConfSchemaById(configurationSchemaId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editConfigurationSchema * (org.kaaproject.kaa.common.dto.ConfigurationSchemaDto) */ @Override public ConfigurationSchemaDto editConfigurationSchema( ConfigurationSchemaDto configurationSchema) throws ControlServiceException { ConfigurationSchemaDto confSchema = null; try { confSchema = configurationService.saveConfSchema(configurationSchema); } catch (IncorrectParameterException ex) { LOG.error("Can't generate protocol schema. Can't save configuration schema."); throw new ControlServiceException(ex); } return confSchema; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getProfileSchemasByApplicationId(java.lang.String) */ @Override public List<EndpointProfileSchemaDto> getProfileSchemasByApplicationId( String applicationId) throws ControlServiceException { return profileService.findProfileSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getProfileSchema * (java.lang.String) */ @Override public EndpointProfileSchemaDto getProfileSchema(String profileSchemaId) throws ControlServiceException { return profileService.findProfileSchemaById(profileSchemaId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getProfileSchemaByApplicationIdAndVersion (java.lang.String, int) */ @Override public EndpointProfileSchemaDto getProfileSchemaByApplicationIdAndVersion( String applicationId, int version) throws ControlServiceException { return profileService.findProfileSchemaByAppIdAndVersion(applicationId, version); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editProfileSchema (org.kaaproject.kaa.common.dto.ProfileSchemaDto) */ @Override public EndpointProfileSchemaDto editProfileSchema(EndpointProfileSchemaDto profileSchema) throws ControlServiceException { return profileService.saveProfileSchema(profileSchema); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getServerProfileSchemasByApplicationId(java.lang.String) */ @Override public List<ServerProfileSchemaDto> getServerProfileSchemasByApplicationId( String applicationId) throws ControlServiceException { return serverProfileService.findServerProfileSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getServerProfileSchema(java.lang.String) */ @Override public ServerProfileSchemaDto getServerProfileSchema(String serverProfileSchemaId) throws ControlServiceException { return serverProfileService.findServerProfileSchema(serverProfileSchemaId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getServerProfileSchemaByApplicationIdAndVersion(java.lang.String, int) */ @Override public ServerProfileSchemaDto getServerProfileSchemaByApplicationIdAndVersion( String applicationId, int version) throws ControlServiceException { return serverProfileService.findServerProfileSchemaByAppIdAndVersion(applicationId, version); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editServerProfileSchema * (org.kaaproject.kaa.common.dto.ServerProfileSchemaDto) */ @Override public ServerProfileSchemaDto saveServerProfileSchema(ServerProfileSchemaDto serverProfileSchema) throws ControlServiceException { if (isNotBlank(serverProfileSchema.getCtlSchemaId())) { return serverProfileService.saveServerProfileSchema(serverProfileSchema); } else { LOG.error("Server profile schema has no CTL schema ID"); throw new ControlServiceException("Server profile schema has no CTL schema ID"); } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * findLatestServerProfileSchema(java.lang.String) */ @Override public ServerProfileSchemaDto findLatestServerProfileSchema(String applicationId) throws ControlServiceException { return serverProfileService.findLatestServerProfileSchema(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEndpointGroupsByApplicationId(java.lang.String) */ @Override public List<EndpointGroupDto> getEndpointGroupsByApplicationId(String applicationId) throws ControlServiceException { return endpointService.findEndpointGroupsByAppId(applicationId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getEndpointGroup * (java.lang.String) */ @Override public EndpointGroupDto getEndpointGroup(String endpointGroupId) throws ControlServiceException { return endpointService.findEndpointGroupById(endpointGroupId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editEndpointGroup (org.kaaproject.kaa.common.dto.EndpointGroupDto) */ @Override public EndpointGroupDto editEndpointGroup(EndpointGroupDto endpointGroup) throws ControlServiceException { return endpointService.saveEndpointGroup(endpointGroup); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteEndpointGroup (java.lang.String) */ @Override public void deleteEndpointGroup(String endpointGroupId) throws ControlServiceException { ChangeNotificationDto notification = endpointService.removeEndpointGroupById(endpointGroupId); if (notification != null) { notifyEndpoints(notification, null, null); } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * removeTopicsFromEndpointGroup(java.lang.String, java.lang.String) */ @Override public EndpointGroupDto removeTopicsFromEndpointGroup(String endpointGroupId, String topicId) throws ControlServiceException { return notifyAndGetPayload(endpointService.removeTopicFromEndpointGroup(endpointGroupId, topicId)); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * addTopicsToEndpointGroup(java.lang.String, java.lang.String) */ @Override public EndpointGroupDto addTopicsToEndpointGroup(String endpointGroupId, String topicId) throws ControlServiceException { return notifyAndGetPayload(endpointService.addTopicToEndpointGroup(endpointGroupId, topicId)); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getProfileFilter * (java.lang.String) */ @Override public ProfileFilterDto getProfileFilter(String profileFilterId) throws ControlServiceException { return profileService.findProfileFilterById(profileFilterId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getProfileFilterRecordsByEndpointGroupId(java.lang.String, boolean) */ @Override public List<ProfileFilterRecordDto> getProfileFilterRecordsByEndpointGroupId( String endpointGroupId, boolean includeDeprecated) throws ControlServiceException { return new ArrayList<>(profileService.findAllProfileFilterRecordsByEndpointGroupId( endpointGroupId, includeDeprecated)); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getProfileFilterRecord(java.lang.String, java.lang.String) */ @Override public ProfileFilterRecordDto getProfileFilterRecord(String endpointProfileSchemaId, String serverProfileSchemaId, String endpointGroupId) throws ControlServiceException { return profileService.findProfileFilterRecordBySchemaIdAndEndpointGroupId( endpointProfileSchemaId, serverProfileSchemaId, endpointGroupId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getVacantProfileSchemasByEndpointGroupId(java.lang.String) */ @Override public List<ProfileVersionPairDto> getVacantProfileSchemasByEndpointGroupId( String endpointGroupId) throws ControlServiceException { return profileService.findVacantSchemasByEndpointGroupId(endpointGroupId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editProfileFilter (org.kaaproject.kaa.common.dto.ProfileFilterDto) */ @Override public ProfileFilterDto editProfileFilter(ProfileFilterDto profileFilter) throws ControlServiceException { return profileService.saveProfileFilter(profileFilter); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getConfigurationRecordsByEndpointGroupId(java.lang.String, boolean) */ @Override public List<ConfigurationRecordDto> getConfigurationRecordsByEndpointGroupId( String endpointGroupId, boolean includeDeprecated) throws ControlServiceException { return new ArrayList<>(configurationService.findAllConfigurationRecordsByEndpointGroupId( endpointGroupId, includeDeprecated)); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getConfigurationRecord(java.lang.String, java.lang.String) */ @Override public ConfigurationRecordDto getConfigurationRecord(String schemaId, String endpointGroupId) throws ControlServiceException { return configurationService.findConfigurationRecordBySchemaIdAndEndpointGroupId(schemaId, endpointGroupId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getVacantConfigurationSchemasByEndpointGroupId(java.lang.String) */ @Override public List<VersionDto> getVacantConfigurationSchemasByEndpointGroupId(String endpointGroupId) throws ControlServiceException { return configurationService.findVacantSchemasByEndpointGroupId(endpointGroupId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getConfiguration * (java.lang.String) */ @Override public ConfigurationDto getConfiguration(String configurationId) throws ControlServiceException { return configurationService.findConfigurationById(configurationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editConfiguration (org.kaaproject.kaa.common.dto.ConfigurationDto) */ @Override public ConfigurationDto editConfiguration(ConfigurationDto configuration) throws ControlServiceException { return configurationService.saveConfiguration(configuration); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editUserConfiguration * (org.kaaproject.kaa.common.dto.EndpointUserConfigurationDto) */ @Override public void editUserConfiguration(EndpointUserConfigurationDto configuration) throws ControlServiceException { ApplicationDto appDto = applicationService.findAppByApplicationToken( configuration.getAppToken()); EndpointUserDto userDto = endpointService.findEndpointUserByExternalIdAndTenantId( configuration.getUserId(), appDto.getTenantId()); if (userDto == null) { throw new NotFoundException("Specified user not found!"); } configuration.setUserId(userDto.getId()); configuration = userConfigurationService.saveUserConfiguration(configuration); EndpointObjectHash hash = EndpointObjectHash.fromString(configuration.getBody()); checkNeighbors(); OperationsNodeInfo server = resolve(configuration.getUserId()); if (server != null) { UserConfigurationUpdate msg = new UserConfigurationUpdate(appDto.getTenantId(), configuration.getUserId(), configuration.getAppToken(), configuration.getSchemaVersion(), hash.getDataBuf()); if (LOG.isTraceEnabled()) { LOG.trace("Sending message {} to [{}]", msg, Neighbors.getServerId( server.getConnectionInfo())); } neighbors.sendMessage(server.getConnectionInfo(), OperationsServiceMsg.fromUpdate(msg)); } else { LOG.warn("Can't find server for user [{}]", configuration.getUserId()); } } /** * Check neighbors. */ private void checkNeighbors() { if (neighbors == null) { synchronized (zkLock) { if (neighbors == null) { neighbors = new Neighbors<>( KaaThriftService.OPERATIONS_SERVICE, new NeighborTemplate<OperationsServiceMsg>() { @Override public void process(Iface client, List<OperationsServiceMsg> messages) throws TException { OperationsServiceMsg.dispatch(client, messages); } @Override public void onServerError(String serverId, Exception ex) { LOG.error("Can't send configuration update to {}", serverId, ex); } }, neighborConnectionsSize); ControlNode zkNode = controlZkService.getControlZkNode(); neighbors.setZkNode( KaaThriftService.KAA_NODE_SERVICE, zkNode.getControlServerInfo().getConnectionInfo(), zkNode); } } } } @Override public EndpointSpecificConfigurationDto editEndpointSpecificConfiguration(EndpointSpecificConfigurationDto configuration) { configuration = endpointSpecificConfigurationService.save(configuration); sendEndpointConfigurationRefreshMessage(configuration); return configuration; } @Override public EndpointSpecificConfigurationDto findEndpointSpecificConfiguration(byte[] endpointKeyHash, Integer confSchemaVersion) { Optional<EndpointSpecificConfigurationDto> result; if (confSchemaVersion == null) { result = endpointSpecificConfigurationService.findActiveConfigurationByEndpointKeyHash(endpointKeyHash); } else { result = endpointSpecificConfigurationService.findByEndpointKeyHashAndConfSchemaVersion(endpointKeyHash, confSchemaVersion); } return result.orElseThrow(() -> new NotFoundException("Endpoint specific configuration not found")); } @Override public EndpointSpecificConfigurationDto deleteEndpointSpecificConfiguration(byte[] endpointKeyHash, Integer confSchemaVersion) { Optional<EndpointSpecificConfigurationDto> result; if (confSchemaVersion == null) { result = endpointSpecificConfigurationService.deleteActiveConfigurationByEndpointKeyHash(endpointKeyHash); } else { result = endpointSpecificConfigurationService.deleteByEndpointKeyHashAndConfSchemaVersion(endpointKeyHash, confSchemaVersion); } EndpointSpecificConfigurationDto configuration = result .orElseThrow(() -> new NotFoundException("Endpoint specific configuration not found")); sendEndpointConfigurationRefreshMessage(configuration); return configuration; } private void sendEndpointConfigurationRefreshMessage(EndpointSpecificConfigurationDto configuration) { byte[] endpointKeyHashBytes = configuration.getEndpointKeyHash(); EndpointProfileDto endpointProfile = endpointService.findEndpointProfileByKeyHash(endpointKeyHashBytes); if (!configuration.getConfigurationSchemaVersion().equals(endpointProfile.getConfigurationVersion())) { return; } checkNeighbors(); String endpointKeyHash = Base64Util.encode(configuration.getEndpointKeyHash()); ApplicationDto appDto = applicationService.findAppById(endpointProfile.getApplicationId()); OperationsNodeInfo server = resolve(endpointKeyHash); if (server != null) { ThriftEndpointConfigurationRefreshMessage msg = new ThriftEndpointConfigurationRefreshMessage(); msg.setAddress(new ThriftEntityAddress(appDto.getTenantId(), appDto.getApplicationToken(), ThriftClusterEntityType.ENDPOINT, ByteBuffer.wrap(endpointKeyHashBytes))); msg.setActorClassifier(ThriftActorClassifier.GLOBAL); if (LOG.isTraceEnabled()) { LOG.trace("Sending message {} to [{}]", msg, Neighbors.getServerId(server.getConnectionInfo())); } neighbors.sendMessage(server.getConnectionInfo(), OperationsServiceMsg.fromEndpointConfigurationRefresh(msg)); } else { LOG.warn("Can't find server for endpoint [{}]", endpointKeyHash); } } /** * Resolve. * * @param entityId the entity id * @return the operations node info */ private OperationsNodeInfo resolve(String entityId) { if (resolver == null) { synchronized (zkLock) { if (resolver == null) { ControlNode zkNode = controlZkService.getControlZkNode(); resolver = new ConsistentHashResolver(zkNode.getCurrentOperationServerNodes(), userHashPartitions); zkNode.addListener(new OperationsNodeListener() { @Override public void onNodeUpdated(OperationsNodeInfo node) { LOG.info("Update of node {} is pushed to resolver {}", node, resolver); resolver.onNodeUpdated(node); } @Override public void onNodeRemoved(OperationsNodeInfo node) { LOG.info("Remove of node {} is pushed to resolver {}", node, resolver); resolver.onNodeRemoved(node); } @Override public void onNodeAdded(OperationsNodeInfo node) { LOG.info("Add of node {} is pushed to resolver {}", node, resolver); resolver.onNodeAdded(node); } }); } } } return resolver.getNode(entityId); } /** * Use when one need to write an OperationsNodeInfo instance to logs. The OperationsNodeInfo * instance has ByteBuffer fields which should be represented in log files as null because their * values are unrepresentative and redundant. * * @param format the format string * @param node the instance of OperationsNodeInfo * @param resolver the instance of OperationsServerResolver */ private void writeLogWithoutByteBuffer(String format, OperationsNodeInfo node, OperationsServerResolver resolver) { // Temporary remove connection info for transports Map<TransportMetaData, Map<VersionConnectionInfoPair, ByteBuffer>> transportMetaData = new HashMap<>(); node.getTransports().forEach(transport -> transportMetaData.put(transport, removeTransportConnectionInfo(transport))); // Temporary remove public key final ByteBuffer publicKey = node.getConnectionInfo().getPublicKey(); node.getConnectionInfo().setPublicKey(null); LOG.info(format, node, resolver); // Restore connection info for transports node.getTransports().forEach(transport -> restoreTransportConnectionInfo(transport, transportMetaData.get(transport))); // Restore public key node.getConnectionInfo().setPublicKey(publicKey); } private Map<VersionConnectionInfoPair, ByteBuffer> removeTransportConnectionInfo(TransportMetaData transport) { Map<VersionConnectionInfoPair, ByteBuffer> infoMap = new HashMap<>(); transport.getConnectionInfo().forEach(connectionInfoPair -> { infoMap.put(connectionInfoPair, connectionInfoPair.getConenctionInfo()); connectionInfoPair.setConenctionInfo(null); }); return infoMap; } private void restoreTransportConnectionInfo(TransportMetaData transport, Map<VersionConnectionInfoPair, ByteBuffer> connectionInfoMap) { transport.getConnectionInfo() .forEach(connectionInfoPair -> connectionInfoPair.setConenctionInfo(getConnectionInfo(connectionInfoPair, connectionInfoMap))); } private ByteBuffer getConnectionInfo(VersionConnectionInfoPair connectionInfoPair, Map<VersionConnectionInfoPair, ByteBuffer> connectionInfoMap) { return connectionInfoMap.entrySet().stream() .filter(entry -> entry.getKey() == connectionInfoPair) .findFirst() .get() .getValue(); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * activateConfiguration(java.lang.String, java.lang.String) */ @Override public ConfigurationDto activateConfiguration(String configurationId, String activatedUsername) throws ControlServiceException { ChangeConfigurationNotification cfgNotification = configurationService .activateConfiguration(configurationId, activatedUsername); ChangeNotificationDto notification = cfgNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, null, cfgNotification.getConfigurationDto()); } return cfgNotification.getConfigurationDto(); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deactivateConfiguration(java.lang.String, java.lang.String) */ @Override public ConfigurationDto deactivateConfiguration(String configurationId, String deactivatedUsername) throws ControlServiceException { ChangeConfigurationNotification cfgNotification = configurationService .deactivateConfiguration(configurationId, deactivatedUsername); ChangeNotificationDto notification = cfgNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, null, cfgNotification.getConfigurationDto()); } return cfgNotification.getConfigurationDto(); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteConfigurationRecord(java.lang.String, java.lang.String, * java.lang.String) */ @Override public void deleteConfigurationRecord(String schemaId, String endpointGroupId, String deactivatedUsername) throws ControlServiceException { ChangeConfigurationNotification cfgNotification = configurationService .deleteConfigurationRecord(schemaId, endpointGroupId, deactivatedUsername); if (cfgNotification != null) { ChangeNotificationDto notification = cfgNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, null, cfgNotification.getConfigurationDto()); } } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * activateProfileFilter(java.lang.String, java.lang.String) */ @Override public ProfileFilterDto activateProfileFilter(String profileFilterId, String activatedUsername) throws ControlServiceException { ChangeProfileFilterNotification cpfNotification = profileService .activateProfileFilter(profileFilterId, activatedUsername); ChangeNotificationDto notification = cpfNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, cpfNotification.getProfileFilterDto(), null); } return cpfNotification.getProfileFilterDto(); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deactivateProfileFilter(java.lang.String, java.lang.String) */ @Override public ProfileFilterDto deactivateProfileFilter(String profileFilterId, String deactivatedUsername) throws ControlServiceException { ChangeProfileFilterNotification cpfNotification = profileService .deactivateProfileFilter(profileFilterId, deactivatedUsername); ChangeNotificationDto notification = cpfNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, cpfNotification.getProfileFilterDto(), null); } return cpfNotification.getProfileFilterDto(); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteProfileFilterRecord(java.lang.String, java.lang.String, * java.lang.String) */ @Override public void deleteProfileFilterRecord(String endpointProfileSchemaId, String serverProfileSchemaId, String endpointGroupId, String deactivatedUsername) throws ControlServiceException { ChangeProfileFilterNotification cpfNotification = profileService .deleteProfileFilterRecord(endpointProfileSchemaId, serverProfileSchemaId, endpointGroupId, deactivatedUsername); if (cpfNotification != null) { ChangeNotificationDto notification = cpfNotification.getChangeNotificationDto(); if (notification != null) { notifyEndpoints(notification, cpfNotification.getProfileFilterDto(), null); } } } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#generateSdk( * org.kaaproject.kaa.common.dto.admin.SdkPropertiesDto) */ @Override public FileData generateSdk(SdkProfileDto sdkProfile, SdkPlatform platform) throws ControlServiceException { EndpointProfileSchemaDto profileSchema = profileService .findProfileSchemaByAppIdAndVersion(sdkProfile.getApplicationId(), sdkProfile.getProfileSchemaVersion()); if (profileSchema == null) { throw new NotFoundException("Profile schema not found!"); } ConfigurationSchemaDto configurationSchema = configurationService .findConfSchemaByAppIdAndVersion(sdkProfile.getApplicationId(), sdkProfile.getConfigurationSchemaVersion()); if (configurationSchema == null) { throw new NotFoundException("Configuration schema not found!"); } ConfigurationDto defaultConfiguration = configurationService .findDefaultConfigurationBySchemaId(configurationSchema.getId()); if (defaultConfiguration == null) { throw new NotFoundException("Default configuration not found!"); } NotificationSchemaDto notificationSchema = notificationService .findNotificationSchemaByAppIdAndTypeAndVersion(sdkProfile.getApplicationId(), NotificationTypeDto.USER, sdkProfile.getNotificationSchemaVersion()); if (notificationSchema == null) { throw new NotFoundException("Notification schema not found!"); } LogSchemaDto logSchema = logSchemaService .findLogSchemaByAppIdAndVersion(sdkProfile.getApplicationId(), sdkProfile.getLogSchemaVersion()); if (logSchema == null) { throw new NotFoundException("Log schema not found!"); } CTLSchemaDto logCtlSchema = getCtlSchemaById(logSchema.getCtlSchemaId()); String logSchemaBodyString = ctlService.flatExportAsString(logCtlSchema); CTLSchemaDto profileCtlSchema = getCtlSchemaById(profileSchema.getCtlSchemaId()); CTLSchemaDto notificationCtlSchema = getCtlSchemaById(notificationSchema.getCtlSchemaId()); CTLSchemaDto confCtlSchema = getCtlSchemaById(configurationSchema.getCtlSchemaId()); String notificationSchemaBodyString = ctlService.flatExportAsString(notificationCtlSchema); String profileSchemaBodyString = ctlService.flatExportAsString(profileCtlSchema); String confSchemaBodyString = ctlService.flatExportAsString(confCtlSchema); DataSchema profileDataSchema = new DataSchema(profileSchemaBodyString); DataSchema confDataSchema = new DataSchema(confSchemaBodyString); DataSchema notificationDataSchema = new DataSchema(notificationSchemaBodyString); ProtocolSchema protocolSchema = new ProtocolSchema(configurationSchema.getProtocolSchema()); DataSchema logDataSchema = new DataSchema(logSchemaBodyString); String profileSchemaBody = profileDataSchema.getRawSchema(); String confSchemaBody = confDataSchema.getRawSchema(); JsonNode json; try { json = new ObjectMapper().readTree(defaultConfiguration.getBody()); } catch (IOException ex) { LOG.error("Unable to convert default configuration data to json", ex); throw new ControlServiceException(ex); } AvroUtils.removeUuids(json); byte[] defaultConfigurationData = GenericAvroConverter.toRawData(json.toString(), confSchemaBody); List<EventFamilyMetadata> eventFamilies = new ArrayList<>(); if (sdkProfile.getAefMapIds() != null) { List<ApplicationEventFamilyMapDto> aefMaps = applicationEventMapService .findApplicationEventFamilyMapsByIds(sdkProfile.getAefMapIds()); for (ApplicationEventFamilyMapDto aefMap : aefMaps) { EventFamilyMetadata efm = new EventFamilyMetadata(); efm.setVersion(aefMap.getVersion()); efm.setEventMaps(aefMap.getEventMaps()); EventClassFamilyDto ecf = eventClassService.findEventClassFamilyById(aefMap.getEcfId()); efm.setEcfName(ecf.getName()); efm.setEcfNamespace(ecf.getNamespace()); efm.setEcfClassName(ecf.getClassName()); List<EventClassFamilyVersionDto> ecfSchemas = eventClassService .findEventClassFamilyVersionsByEcfId(aefMap.getEcfId()); for (EventClassFamilyVersionDto ecfSchema : ecfSchemas) { if (ecfSchema.getVersion() == efm.getVersion()) { List<EventClassDto> records = eventClassService .findEventClassesByFamilyIdVersionAndType(ecf.getId(), ecfSchema.getVersion(), null); efm.setRecords(records); List<CTLSchemaDto> ctlDtos = new ArrayList<>(); List<String> flatEventClassCtlSchemas = new ArrayList<>(); records.forEach(rec -> ctlDtos.add(ctlService.findCtlSchemaById(rec.getCtlSchemaId()))); ctlDtos.forEach( ctlDto -> flatEventClassCtlSchemas.add( new DataSchema(ctlService.flatExportAsString(ctlDto)).getRawSchema() )) ; efm.setRawCtlsSchemas(flatEventClassCtlSchemas); break; } } eventFamilies.add(efm); } } LOG.debug("Sdk profile for sdk generation: {}", sdkProfile); SdkGenerator generator = SdkGeneratorFactory.createSdkGenerator(platform); FileData sdkFile = null; try { sdkFile = generator.generateSdk( Version.PROJECT_VERSION, controlZkService.getCurrentBootstrapNodes(), sdkProfile, profileSchemaBody, notificationDataSchema.getRawSchema(), protocolSchema.getRawSchema(), confSchemaBody, defaultConfigurationData, eventFamilies, logDataSchema.getRawSchema()); } catch (Exception ex) { LOG.error("Unable to generate SDK", ex); throw new ControlServiceException(ex); } sdkFile.setContentType(platform.getContentType()); return sdkFile; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * generateRecordStructureLibrary(java.lang.String, int) */ @Override public FileData generateRecordStructureLibrary(String applicationId, int logSchemaVersion) throws ControlServiceException { ApplicationDto application = applicationService.findAppById(applicationId); if (application == null) { throw new NotFoundException("Application not found!"); } LogSchemaDto logSchema = logSchemaService.findLogSchemaByAppIdAndVersion(applicationId, logSchemaVersion); if (logSchema == null) { throw new NotFoundException("Log schema not found!"); } try { CTLSchemaDto logCtlSchema = getCtlSchemaById(logSchema.getCtlSchemaId()); Schema recordWrapperSchema = RecordWrapperSchemaGenerator .generateRecordWrapperSchema(getFlatSchemaByCtlSchemaId(logCtlSchema.getId())); String fileName = MessageFormatter.arrayFormat(LOG_SCHEMA_LIBRARY_NAME_PATTERN, new Object[] {logSchemaVersion}).getMessage(); return SchemaLibraryGenerator.generateSchemaLibrary(recordWrapperSchema, fileName); } catch (Exception ex) { LOG.error("Unable to generate Record Structure Library", ex); throw new ControlServiceException(ex); } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editNotificationSchema * (org.kaaproject.kaa.common.dto.NotificationSchemaDto) */ @Override public NotificationSchemaDto saveNotificationSchema(NotificationSchemaDto notificationSchema) throws ControlServiceException { return notificationService.saveNotificationSchema(notificationSchema); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getNotificationSchema(java.lang.String) */ @Override public NotificationSchemaDto getNotificationSchema(String notificationSchemaId) throws ControlServiceException { return notificationService.findNotificationSchemaById(notificationSchemaId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getNotificationSchemasByAppId(java.lang.String) */ @Override public List<NotificationSchemaDto> getNotificationSchemasByAppId(String applicationId) throws ControlServiceException { return notificationService.findNotificationSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getUserNotificationSchemasByAppId(java.lang.String) */ @Override public List<VersionDto> getUserNotificationSchemasByAppId(String applicationId) throws ControlServiceException { return notificationService.findUserNotificationSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * findNotificationSchemasByAppIdAndType(java.lang.String, * org.kaaproject.kaa.common.dto.NotificationTypeDto) */ @Override public List<NotificationSchemaDto> findNotificationSchemasByAppIdAndType( String applicationId, NotificationTypeDto type) throws ControlServiceException { return notificationService.findNotificationSchemasByAppIdAndType(applicationId, type); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editLogSchema * (org.kaaproject.kaa.common.dto.logs.LogSchemaDto) */ @Override public LogSchemaDto saveLogSchema(LogSchemaDto logSchemaDto) throws ControlServiceException { return logSchemaService.saveLogSchema(logSchemaDto); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editLogSchema * (org.kaaproject.kaa.common.dto.logs.LogSchemaDto) */ @Override public String getFlatSchemaByCtlSchemaId(String schemaId) throws ControlServiceException { CTLSchemaDto ctlSchemaDto = getCtlSchemaById(schemaId); return ctlService.flatExportAsString(ctlSchemaDto); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getLogSchemasByApplicationId(java.lang.String) */ @Override public List<LogSchemaDto> getLogSchemasByApplicationId(String applicationId) throws ControlServiceException { return logSchemaService.findLogSchemasByAppId(applicationId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getLogSchema * (java.lang.String) */ @Override public LogSchemaDto getLogSchema(String logSchemaId) throws ControlServiceException { return logSchemaService.findLogSchemaById(logSchemaId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getLogSchemaByApplicationIdAndVersion(java.lang.String, int) */ @Override public LogSchemaDto getLogSchemaByApplicationIdAndVersion( String applicationId, int version) throws ControlServiceException { return logSchemaService.findLogSchemaByAppIdAndVersion(applicationId, version); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editNotification * (org.kaaproject.kaa.common.dto.NotificationDto) */ @Override public NotificationDto editNotification(NotificationDto notification) throws ControlServiceException { return notifyAndGetPayload(notificationService.saveNotification(notification)); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getNotification * (java.lang.String) */ @Override public NotificationDto getNotification(String notificationId) throws ControlServiceException { return notificationService.findNotificationById(notificationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getNotificationsByTopicId(java.lang.String) */ @Override public List<NotificationDto> getNotificationsByTopicId(String topicId) throws ControlServiceException { return notificationService.findNotificationsByTopicId(topicId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editTopic(org * .kaaproject.kaa.common.dto.TopicDto) */ @Override public TopicDto editTopic(TopicDto topic) throws ControlServiceException { return topicService.saveTopic(topic); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getTopic(java * .lang.String) */ @Override public TopicDto getTopic(String topicId) throws ControlServiceException { return topicService.findTopicById(topicId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getTopicByAppId * (java.lang.String) */ @Override public List<TopicDto> getTopicByAppId(String appId) throws ControlServiceException { return topicService.findTopicsByAppId(appId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getTopicByEndpointGroupId(java.lang.String) */ @Override public List<TopicDto> getTopicByEndpointGroupId(String endpointGroupId) throws ControlServiceException { return topicService.findTopicsByEndpointGroupId(endpointGroupId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getVacantTopicByEndpointGroupId(java.lang.String) */ @Override public List<TopicDto> getVacantTopicByEndpointGroupId(String endpointGroupId) throws ControlServiceException { return topicService.findVacantTopicsByEndpointGroupId(endpointGroupId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#deleteTopicById * (java.lang.String) */ @Override public void deleteTopicById(String topicId) throws ControlServiceException { for (UpdateNotificationDto<EndpointGroupDto> dto : topicService.removeTopicById(topicId)) { notifyAndGetPayload(dto); } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getUnicastNotification(java.lang.String) */ @Override public EndpointNotificationDto getUnicastNotification(String notificationId) throws ControlServiceException { return notificationService.findUnicastNotificationById(notificationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editUnicastNotification * (org.kaaproject.kaa.common.dto.EndpointNotificationDto) */ @Override public EndpointNotificationDto editUnicastNotification(EndpointNotificationDto notification) throws ControlServiceException { UpdateNotificationDto<EndpointNotificationDto> updateNotification = notificationService.saveUnicastNotification(notification); EndpointNotificationDto notificationDto = updateNotification.getPayload(); checkNeighbors(); String endpointId = Base64Util.encode(notificationDto.getEndpointKeyHash()); OperationsNodeInfo server = resolve(endpointId); if (server != null) { ApplicationDto appDto = getApplication(updateNotification.getAppId()); ThriftUnicastNotificationMessage nf = new ThriftUnicastNotificationMessage(); nf.setAddress( new ThriftEntityAddress( appDto.getTenantId(), appDto.getApplicationToken(), ThriftClusterEntityType.ENDPOINT, ByteBuffer.wrap(notificationDto.getEndpointKeyHash()) ) ); nf.setActorClassifier(ThriftActorClassifier.GLOBAL); nf.setNotificationId(notificationDto.getId()); if (LOG.isTraceEnabled()) { LOG.trace("Sending message {} to [{}]", nf, Neighbors.getServerId(server.getConnectionInfo())); } neighbors.sendMessage(server.getConnectionInfo(), OperationsServiceMsg.fromNotification(nf)); } else { LOG.warn("Can't find server for endpoint [{}]", endpointId); } return updateNotification.getPayload(); } @Override public EndpointProfileDto updateServerProfile(String endpointKeyHash, int version, String serverProfile) throws ControlServiceException { EndpointProfileDto endpointProfileDto = serverProfileService.saveServerProfile( Base64.decodeBase64(endpointKeyHash), version, serverProfile); checkNeighbors(); OperationsNodeInfo server = resolve(endpointKeyHash); if (server != null) { ApplicationDto appDto = getApplication(endpointProfileDto.getApplicationId()); ThriftServerProfileUpdateMessage nf = new ThriftServerProfileUpdateMessage(); nf.setAddress( new ThriftEntityAddress( appDto.getTenantId(), appDto.getApplicationToken(), ThriftClusterEntityType.ENDPOINT, ByteBuffer.wrap(endpointProfileDto.getEndpointKeyHash()) ) ); nf.setActorClassifier(ThriftActorClassifier.GLOBAL); if (LOG.isTraceEnabled()) { LOG.trace("Sending message {} to [{}]", nf, Neighbors.getServerId(server.getConnectionInfo())); } neighbors.sendMessage(server.getConnectionInfo(), OperationsServiceMsg.fromServerProfileUpdateMessage(nf)); } else { LOG.warn("Can't find server for endpoint [{}]", endpointKeyHash); } return endpointProfileDto; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getUnicastNotificationsByKeyHash(byte[]) */ @Override public List<EndpointNotificationDto> getUnicastNotificationsByKeyHash(byte[] keyhash) throws ControlServiceException { List<EndpointNotificationDto> structList = Collections.emptyList(); if (keyhash != null) { structList = notificationService.findUnicastNotificationsByKeyHash(keyhash); } return structList; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getConfigurationSchemaVersionsByApplicationId(java.lang.String) */ @Override public List<VersionDto> getConfigurationSchemaVersionsByApplicationId(String applicationId) throws ControlServiceException { return configurationService.findConfigurationSchemaVersionsByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getProfileSchemaVersionsByApplicationId(java.lang.String) */ @Override public List<VersionDto> getProfileSchemaVersionsByApplicationId(String applicationId) throws ControlServiceException { return profileService.findProfileSchemaVersionsByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getNotificationSchemaVersionsByApplicationId(java.lang.String) */ @Override public List<VersionDto> getNotificationSchemaVersionsByApplicationId(String applicationId) throws ControlServiceException { return notificationService.findNotificationSchemaVersionsByAppId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getLogSchemaVersionsByApplicationId(java.lang.String) */ @Override public List<VersionDto> getLogSchemaVersionsByApplicationId(String applicationId) throws ControlServiceException { return logSchemaService.findLogSchemaVersionsByApplicationId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editEventClassFamily * (org.kaaproject.kaa.common.dto.event.EventClassFamilyVersionDto) */ @Override public EventClassFamilyDto editEventClassFamily(EventClassFamilyDto eventClassFamily) throws ControlServiceException { return eventClassService.saveEventClassFamily(eventClassFamily); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassFamiliesByTenantId(java.lang.String) */ @Override public List<EventClassFamilyDto> getEventClassFamiliesByTenantId(String tenantId) throws ControlServiceException { return eventClassService.findEventClassFamiliesByTenantId(tenantId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassFamily (java.lang.String) */ @Override public EventClassFamilyDto getEventClassFamily(String eventClassFamilyId) throws ControlServiceException { return eventClassService.findEventClassFamilyById(eventClassFamilyId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassFamilyVersions (java.lang.String) */ @Override public List<EventClassFamilyVersionDto> getEventClassFamilyVersions(String eventClassFamilyId) throws ControlServiceException { return eventClassService.findEventClassFamilyVersionsByEcfId(eventClassFamilyId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * addEventClassFamilyVersion(java.lang.String, java.lang.String, * java.lang.String) */ @Override public void addEventClassFamilyVersion(String eventClassFamilyId, EventClassFamilyVersionDto eventClassFamilyVersion, String createdUsername) throws ControlServiceException { eventClassService.addEventClassFamilyVersion(eventClassFamilyId, eventClassFamilyVersion, createdUsername); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassesByFamilyIdVersionAndType(java.lang.String, int, * org.kaaproject.kaa.common.dto.event.EventClassType) */ @Override public List<EventClassDto> getEventClassesByFamilyIdVersionAndType( String ecfId, int version, EventClassType type) throws ControlServiceException { return eventClassService.findEventClassesByFamilyIdVersionAndType(ecfId, version, type); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassesByFamilyIdVersionAndType(java.lang.String, int, * org.kaaproject.kaa.common.dto.event.EventClassType) */ @Override public EventClassDto getEventClassById(String eventClassId) throws ControlServiceException { return eventClassService.findEventClassById(eventClassId); } @Override public boolean validateEventClassFamilyFqns(String ecfId, List<String> fqns) { return eventClassService.validateEventClassFamilyFqns(ecfId, fqns); } @Override public Set<String> getFqnSetForEcf(String ecfId) { return eventClassService.getFqnSetForEcf(ecfId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * validateEcfListInSdkProfile(List<org.kaaproject.kaa.common.dto.event.AefMapInfoDto> ecfList) */ @Override public void validateEcfListInSdkProfile(List<AefMapInfoDto> ecfList) throws ControlServiceException { if (!eventClassService.isValidEcfListInSdkProfile(ecfList)) { throw new ControlServiceException("You have chosen event class families," + " where event classes have the same FQNs."); } } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * editApplicationEventFamilyMap * (org.kaaproject.kaa.common.dto.event.ApplicationEventFamilyMapDto) */ @Override public ApplicationEventFamilyMapDto editApplicationEventFamilyMap( ApplicationEventFamilyMapDto applicationEventFamilyMap) throws ControlServiceException { return applicationEventMapService.saveApplicationEventFamilyMap(applicationEventFamilyMap); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getApplicationEventFamilyMap(java.lang.String) */ @Override public ApplicationEventFamilyMapDto getApplicationEventFamilyMap( String applicationEventFamilyMapId) throws ControlServiceException { return applicationEventMapService .findApplicationEventFamilyMapById(applicationEventFamilyMapId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getApplicationEventFamilyMapsByApplicationId(java.lang.String) */ @Override public List<ApplicationEventFamilyMapDto> getApplicationEventFamilyMapsByApplicationId( String applicationId) throws ControlServiceException { return applicationEventMapService.findApplicationEventFamilyMapsByApplicationId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getVacantEventClassFamiliesByApplicationId(java.lang.String) */ @Override public List<EcfInfoDto> getVacantEventClassFamiliesByApplicationId(String applicationId) throws ControlServiceException { return applicationEventMapService.findVacantEventClassFamiliesByApplicationId(applicationId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getEventClassFamiliesByApplicationId(java.lang.String) */ @Override public List<AefMapInfoDto> getEventClassFamiliesByApplicationId(String applicationId) throws ControlServiceException { return applicationEventMapService.findEventClassFamiliesByApplicationId(applicationId); } /** * Notify endpoints. * * @param notification the notification * @param profileFilter the profile filter * @param configuration the configuration */ private void notifyEndpoints(ChangeNotificationDto notification, ProfileFilterDto profileFilter, ConfigurationDto configuration) { Notification thriftNotification = new Notification(); thriftNotification.setAppId(notification.getAppId()); thriftNotification.setAppSeqNumber(notification.getAppSeqNumber()); thriftNotification.setGroupId(notification.getGroupId()); thriftNotification.setGroupSeqNumber(notification.getGroupSeqNumber()); if (profileFilter != null) { thriftNotification.setProfileFilterId(profileFilter.getId()); thriftNotification.setProfileFilterSeqNumber(profileFilter.getSequenceNumber()); } if (configuration != null) { thriftNotification.setConfigurationId(configuration.getId()); thriftNotification.setConfigurationSeqNumber(configuration.getSequenceNumber()); } controlZkService.sendEndpointNotification(thriftNotification); } /** * Notify endpoints. * * @param notification the notification */ private <T> void notifyEndpoints(UpdateNotificationDto<T> notification) { controlZkService.sendEndpointNotification(toNotification(notification)); } private <T> Notification toNotification(UpdateNotificationDto<T> notification) { Notification thriftNotification = new Notification(); thriftNotification.setAppId(notification.getAppId()); thriftNotification.setAppSeqNumber(notification.getAppSeqNumber()); thriftNotification.setGroupId(notification.getGroupId()); thriftNotification.setGroupSeqNumber(notification.getGroupSeqNumber()); thriftNotification.setTopicId(notification.getTopicId()); thriftNotification.setOp(getOperation(notification.getChangeType())); T payload = notification.getPayload(); if (payload != null) { if (payload instanceof NotificationDto) { NotificationDto dto = (NotificationDto) payload; thriftNotification.setNotificationId(dto.getId()); } } return thriftNotification; } /** * Notify and get payload. * * @param notification the notification * @return the checks for id */ private <T> T notifyAndGetPayload(UpdateNotificationDto<T> notification) { T result = null; if (notification != null) { notifyEndpoints(notification); T payload = notification.getPayload(); if (payload instanceof HasId && payload != null) { result = payload; } } return result; } /** * Gets the operation. * * @param type the type * @return the operation */ private Operation getOperation(ChangeType type) { Operation operation = null; if (type != null) { try { operation = Operation.valueOf(type.name()); } catch (IllegalArgumentException ex) { LOG.info("Unsupported change type. Check Operation and ChangeType enums.", ex); } } return operation; } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getEndpointUsers * () */ @Override public List<EndpointUserDto> getEndpointUsers() throws ControlServiceException { return endpointService.findAllEndpointUsers(); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getEndpointUser * (java.lang.String) */ @Override public EndpointUserDto getEndpointUser(String endpointUserId) throws ControlServiceException { return endpointService.findEndpointUserById(endpointUserId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * generateEndpointUserAccessToken(java.lang.String, java.lang.String) */ @Override public String generateEndpointUserAccessToken(String externalUid, String tenantId) throws ControlServiceException { return endpointService.generateEndpointUserAccessToken(externalUid, tenantId); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getLogAppendersByApplicationId(java.lang.String) */ @Override public List<LogAppenderDto> getLogAppendersByApplicationId(String applicationId) throws ControlServiceException { return logAppenderService.findAllAppendersByAppId(applicationId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getLogAppender * (java.lang.String) */ @Override public LogAppenderDto getLogAppender(String logAppenderId) throws ControlServiceException { return logAppenderService.findLogAppenderById(logAppenderId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editLogAppender * (org.kaaproject.kaa.common.dto.logs.LogAppenderDto) */ @Override public LogAppenderDto editLogAppender(LogAppenderDto logAppender) throws ControlServiceException { LogAppenderDto saved = null; if (logAppender != null) { saved = logAppenderService.saveLogAppender(logAppender); if (saved != null) { Notification thriftNotification = new Notification(); thriftNotification.setAppId(saved.getApplicationId()); thriftNotification.setAppenderId(saved.getId()); if (logAppender.getId() == null) { LOG.info("Add new log appender ..."); thriftNotification.setOp(Operation.ADD_LOG_APPENDER); LOG.info("Send notification to operation servers about new appender."); } else { thriftNotification.setOp(Operation.UPDATE_LOG_APPENDER); LOG.info("Send notification to operation servers about update appender configuration."); } controlZkService.sendEndpointNotification(thriftNotification); } } return saved; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteLogAppender (java.lang.String) */ @Override public void deleteLogAppender(String logAppenderId) throws ControlServiceException { LogAppenderDto logAppenderDto = logAppenderService.findLogAppenderById(logAppenderId); LOG.info("Remove log appender ..."); logAppenderService.removeLogAppenderById(logAppenderId); Notification thriftNotification = new Notification(); thriftNotification.setAppId(logAppenderDto.getApplicationId()); thriftNotification.setAppenderId(logAppenderDto.getId()); thriftNotification.setOp(Operation.REMOVE_LOG_APPENDER); LOG.info("Send notification to operation servers about removing appender."); controlZkService.sendEndpointNotification(thriftNotification); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getUserVerifiersByApplicationId(java.lang.String) */ @Override public List<UserVerifierDto> getUserVerifiersByApplicationId(String applicationId) throws ControlServiceException { return userVerifierService.findUserVerifiersByAppId(applicationId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#getUserVerifier * (java.lang.String) */ @Override public UserVerifierDto getUserVerifier(String userVerifierId) throws ControlServiceException { return userVerifierService.findUserVerifierById(userVerifierId); } /* * (non-Javadoc) * * @see * org.kaaproject.kaa.server.control.service.ControlService#editUserVerifier * (org.kaaproject.kaa.common.dto.user.UserVerifierDto) */ @Override public UserVerifierDto editUserVerifier(UserVerifierDto userVerifier) throws ControlServiceException { LOG.info("Adding new user verifier {}", userVerifier); UserVerifierDto saved = null; if (userVerifier != null) { saved = userVerifierService.saveUserVerifier(userVerifier); LOG.info("Saved user verifier {}", saved); if (saved != null) { Notification thriftNotification = new Notification(); thriftNotification.setAppId(saved.getApplicationId()); thriftNotification.setUserVerifierToken(saved.getVerifierToken()); if (userVerifier.getId() == null) { LOG.info("Add new user verifier ..."); thriftNotification.setOp(Operation.ADD_USER_VERIFIER); LOG.info("Send notification to operation servers about new user verifier."); } else { thriftNotification.setOp(Operation.UPDATE_USER_VERIFIER); LOG.info("Send notification to operation servers about update " + "user verifier configuration."); } controlZkService.sendEndpointNotification(thriftNotification); } } return saved; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * deleteUserVerifier (java.lang.String) */ @Override public void deleteUserVerifier(String userVerifierId) throws ControlServiceException { UserVerifierDto userVerifierDto = userVerifierService.findUserVerifierById(userVerifierId); LOG.info("Remove user verifier ..."); userVerifierService.removeUserVerifierById(userVerifierId); Notification thriftNotification = new Notification(); thriftNotification.setAppId(userVerifierDto.getApplicationId()); thriftNotification.setUserVerifierToken(userVerifierDto.getVerifierToken()); thriftNotification.setOp(Operation.REMOVE_USER_VERIFIER); LOG.info("Send notification to operation servers about removing user verifier."); controlZkService.sendEndpointNotification(thriftNotification); } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getRecordStructureSchema(java.lang.String, int) */ @Override public FileData getRecordStructureSchema(String applicationId, int logSchemaVersion) throws ControlServiceException { ApplicationDto application = applicationService.findAppById(applicationId); if (application == null) { throw new NotFoundException("Application not found!"); } LogSchemaDto logSchema = logSchemaService .findLogSchemaByAppIdAndVersion(applicationId, logSchemaVersion); if (logSchema == null) { throw new NotFoundException("Log schema not found!"); } Schema recordWrapperSchema = null; try { CTLSchemaDto logCtlSchema = getCtlSchemaById(logSchema.getCtlSchemaId()); recordWrapperSchema = RecordWrapperSchemaGenerator .generateRecordWrapperSchema(logCtlSchema.getBody()); } catch (IOException ex) { LOG.error("Unable to get Record Structure Schema", ex); throw new ControlServiceException(ex); } String libraryFileName = MessageFormatter .arrayFormat(SCHEMA_NAME_PATTERN, new Object[] {logSchemaVersion}).getMessage(); String schemaInJson = recordWrapperSchema.toString(true); byte[] schemaData = schemaInJson.getBytes(StandardCharsets.UTF_8); FileData schema = new FileData(); schema.setFileName(libraryFileName); schema.setFileData(schemaData); return schema; } /* * (non-Javadoc) * * @see org.kaaproject.kaa.server.control.service.ControlService# * getRecordStructureData(org.kaaproject.kaa.common.dto.admin.RecordKey) */ @Override public FileData getRecordStructureData(RecordKey key) throws ControlServiceException { ApplicationDto application = applicationService.findAppById(key.getApplicationId()); if (application == null) { throw new NotFoundException("Application not found!"); } FileData data = new FileData(); if (RecordFiles.LOG_LIBRARY.equals(key.getRecordFiles())) { data = generateRecordStructureLibrary(key.getApplicationId(), key.getSchemaVersion()); } else { AbstractSchemaDto schemaDto = null; ConfigurationSchemaDto confSchemaDto = null; String fileName = null; String schema = null; switch (key.getRecordFiles()) { case LOG_SCHEMA: throw new RuntimeException("Not implemented!"); case CONFIGURATION_SCHEMA: throw new RuntimeException("Not implemented!"); case CONFIGURATION_BASE_SCHEMA: confSchemaDto = configurationService .findConfSchemaByAppIdAndVersion(key.getApplicationId(), key.getSchemaVersion()); checkSchema(confSchemaDto, RecordFiles.CONFIGURATION_BASE_SCHEMA); schema = confSchemaDto.getBaseSchema(); fileName = MessageFormatter .arrayFormat(DATA_NAME_PATTERN, new Object[] { "configuration-base", key.getSchemaVersion() }) .getMessage(); break; case CONFIGURATION_OVERRIDE_SCHEMA: confSchemaDto = configurationService .findConfSchemaByAppIdAndVersion(key.getApplicationId(), key.getSchemaVersion()); checkSchema(confSchemaDto, RecordFiles.CONFIGURATION_OVERRIDE_SCHEMA); schema = confSchemaDto.getOverrideSchema(); fileName = MessageFormatter .arrayFormat(DATA_NAME_PATTERN, new Object[] { "configuration-override", key.getSchemaVersion()}) .getMessage(); break; case NOTIFICATION_SCHEMA: throw new RuntimeException("Not implemented!"); case PROFILE_SCHEMA: throw new RuntimeException("Not implemented!"); case SERVER_PROFILE_SCHEMA: throw new RuntimeException("Not implemented!"); default: break; } byte[] schemaData = schema.getBytes(StandardCharsets.UTF_8); data.setFileName(fileName); data.setFileData(schemaData); } return data; } @Override public EndpointProfilesBodyDto getEndpointProfileBodyByEndpointGroupId(PageLinkDto pageLinkDto) throws ControlServiceException { return endpointService.findEndpointProfileBodyByEndpointGroupId(pageLinkDto); } @Override public EndpointProfileDto getEndpointProfileByKeyHash(String endpointProfileKeyHash) throws ControlServiceException { return endpointService.findEndpointProfileByKeyHash( Base64.decodeBase64(endpointProfileKeyHash) ); } @Override public EndpointProfileBodyDto getEndpointProfileBodyByKeyHash(String endpointProfileKeyHash) throws ControlServiceException { return endpointService.findEndpointProfileBodyByKeyHash( Base64.decodeBase64(endpointProfileKeyHash) ); } @Override public EndpointProfilesPageDto getEndpointProfileByEndpointGroupId(PageLinkDto pageLinkDto) throws ControlServiceException { return endpointService.findEndpointProfileByEndpointGroupId(pageLinkDto); } @Override public SdkProfileDto getSdkProfile(String sdkProfileId) throws ControlServiceException { return sdkProfileService.findSdkProfileById(sdkProfileId); } @Override public List<SdkProfileDto> getSdkProfilesByApplicationId(String applicationId) { return sdkProfileService.findSdkProfilesByApplicationId(applicationId); } @Override public void deleteSdkProfile(String sdkProfileId) throws ControlServiceException { sdkProfileService.removeSdkProfileById(sdkProfileId); } @Override public boolean isSdkProfileUsed(String token) throws ControlServiceException { return sdkProfileService.isSdkProfileUsed(token); } @Override public SdkProfileDto saveSdkProfile(SdkProfileDto sdkProfile) throws ControlServiceException { return sdkProfileService.saveSdkProfile(sdkProfile); } /** * Check schema. * * @param schemaDto the schema dto * @param file the file * @throws NotFoundException the control service exception */ private void checkSchema(VersionDto schemaDto, RecordFiles file) throws NotFoundException { if (schemaDto == null) { throw new NotFoundException("Schema " + file + " not found!"); } } @Override public CTLSchemaDto saveCtlSchema(CTLSchemaDto schema) throws ControlServiceException { return ctlService.saveCtlSchema(schema); } @Override public void deleteCtlSchemaByFqnAndVersionTenantIdAndApplicationId(String fqn, int version, String tenantId, String applicationId) throws ControlServiceException { ctlService.removeCtlSchemaByFqnAndVerAndTenantIdAndApplicationId(fqn, version, tenantId, applicationId); } @Override public CTLSchemaDto getCtlSchemaById(String schemaId) throws ControlServiceException { CTLSchemaDto ctlSchemaDto = ctlService.findCtlSchemaById(schemaId); if (ctlSchemaDto == null) { LOG.error("CTL schema with Id [{}] not found!", schemaId); throw new NotFoundException("CTL schema not found!"); } return ctlSchemaDto; } @Override public CTLSchemaDto getCtlSchemaByFqnVersionTenantIdAndApplicationId(String fqn, int version, String tenantId, String applicationId) throws ControlServiceException { return ctlService.findCtlSchemaByFqnAndVerAndTenantIdAndApplicationId(fqn, version, tenantId, applicationId); } @Override public CTLSchemaDto getCtlSchemaByMetaInfoIdAndVer(String metaInfoId, Integer version) { return ctlService.findByMetaInfoIdAndVer(metaInfoId, version); } @Override public CTLSchemaDto getAnyCtlSchemaByFqnVersionTenantIdAndApplicationId(String fqn, int version, String tenantId, String applicationId) throws ControlServiceException { return ctlService.findAnyCtlSchemaByFqnAndVerAndTenantIdAndApplicationId(fqn, version, tenantId, applicationId); } @Override public List<CtlSchemaMetaInfoDto> getSiblingsByFqnTenantIdAndApplicationId(String fqn, String tenantId, String applicationId) { return ctlService.findSiblingsByFqnTenantIdAndApplicationId(fqn, tenantId, applicationId); } @Override public CtlSchemaMetaInfoDto updateCtlSchemaMetaInfoScope(CtlSchemaMetaInfoDto ctlSchemaMetaInfo) { return ctlService.updateCtlSchemaMetaInfoScope(ctlSchemaMetaInfo); } @Override public List<CtlSchemaMetaInfoDto> getSystemCtlSchemasMetaInfo() throws ControlServiceException { return ctlService.findSystemCtlSchemasMetaInfo(); } @Override public Map<Fqn, List<Integer>> getAvailableCtlSchemaVersionsForSystem() throws ControlServiceException { return extractCtlSchemaVersionsInfo(ctlService.findSystemCtlSchemasMetaInfo()); } @Override public List<CtlSchemaMetaInfoDto> getAvailableCtlSchemasMetaInfoForTenant(String tenantId) throws ControlServiceException { return ctlService.findAvailableCtlSchemasMetaInfoForTenant(tenantId); } @Override public Map<Fqn, List<Integer>> getAvailableCtlSchemaVersionsForTenant(String tenantId) throws ControlServiceException { return extractCtlSchemaVersionsInfo( ctlService.findAvailableCtlSchemasMetaInfoForTenant(tenantId) ); } @Override public List<CtlSchemaMetaInfoDto> getAvailableCtlSchemasMetaInfoForApplication(String tenantId, String appId) throws ControlServiceException { return ctlService.findAvailableCtlSchemasMetaInfoForApplication(tenantId, appId); } @Override public Map<Fqn, List<Integer>> getAvailableCtlSchemaVersionsForApplication(String tenantId, String appId) throws ControlServiceException { return extractCtlSchemaVersionsInfo( ctlService.findAvailableCtlSchemasMetaInfoForApplication(tenantId, appId) ); } private Map<Fqn, List<Integer>> extractCtlSchemaVersionsInfo( List<CtlSchemaMetaInfoDto> ctlSchemaInfos) { Map<Fqn, List<Integer>> ctlSchemaVersions = new HashMap<>(); for (CtlSchemaMetaInfoDto ctlSchemaInfo : ctlSchemaInfos) { ctlSchemaVersions.put(new Fqn(ctlSchemaInfo.getFqn()), ctlSchemaInfo.getVersions()); } return ctlSchemaVersions; } @Override public List<CTLSchemaDto> getCtlSchemaDependents(String schemaId) throws ControlServiceException { return ctlService.findCtlSchemaDependents(schemaId); } @Override public List<CTLSchemaDto> getCtlSchemaDependents(String fqn, int version, String tenantId, String applicationId) throws ControlServiceException { return ctlService.findCtlSchemaDependents(fqn, version, tenantId, applicationId); } @Override public CTLSchemaDto getLatestCtlSchemaByFqnTenantIdAndApplicationId( String fqn, String tenantId, String applicationId) throws ControlServiceException { return ctlService.findLatestCtlSchemaByFqnAndTenantIdAndApplicationId(fqn, tenantId, applicationId); } @Override public CTLSchemaDto getLatestCtlSchemaByMetaInfoId(String metaInfoId) { return ctlService.findLatestByMetaInfoId(metaInfoId); } @Override public List<Integer> getAllCtlSchemaVersionsByFqnTenantIdAndApplicationId( String fqn, String tenantId, String applicationId) throws ControlServiceException { List<CTLSchemaDto> schemas = ctlService.findAllCtlSchemasByFqnAndTenantIdAndApplicationId(fqn, tenantId, applicationId); List<Integer> versions = new ArrayList<>(schemas.size()); for (CTLSchemaDto schema : schemas) { versions.add(schema.getVersion()); } return versions; } public FileData exportCtlSchemaShallow(CTLSchemaDto schema) throws ControlServiceException { return ctlService.shallowExport(schema); } @Override public FileData exportCtlSchemaFlat(CTLSchemaDto schema) throws ControlServiceException { return ctlService.flatExport(schema); } @Override public FileData exportCtlSchemaFlatAsLibrary(CTLSchemaDto schema) throws ControlServiceException { try { Schema avroSchema = ctlService.flatExportAsSchema(schema); String fileName = MessageFormat.format(CTL_LIBRARY_EXPORT_TEMPLATE, schema.getMetaInfo().getFqn(), schema.getVersion()); return SchemaLibraryGenerator.generateSchemaLibrary(avroSchema, fileName); } catch (Exception ex) { LOG.error("Unable to export flat CTL schema as library", ex); throw new ControlServiceException(ex); } } @Override public String exportCtlSchemaFlatAsString(CTLSchemaDto schema) throws ControlServiceException { return ctlService.flatExportAsString(schema); } @Override public Schema exportCtlSchemaFlatAsSchema(CTLSchemaDto schema) throws ControlServiceException { return ctlService.flatExportAsSchema(schema); } @Override public FileData exportCtlSchemaDeep(CTLSchemaDto schema) throws ControlServiceException { return ctlService.deepExport(schema); } @Override public SdkProfileDto findSdkProfileByToken(String sdkToken) throws ControlServiceException { SdkProfileDto result = sdkProfileService.findSdkProfileByToken(sdkToken); if (result != null) { return result; } else { throw new ControlServiceException("Can't find sdk profile by sdk token: " + sdkToken + "!"); } } @Override public List<EndpointProfileDto> getEndpointProfilesByUserExternalIdAndTenantId( String endpointUserExternalId, String tenantId) throws ControlServiceException { return this.endpointService .findEndpointProfilesByExternalIdAndTenantId(endpointUserExternalId, tenantId); } /** * Shutdown of control service neighbors. */ @PreDestroy public void onStop() { if (neighbors != null) { LOG.info("Shutdown of control service neighbors started!"); neighbors.shutdown(); LOG.info("Shutdown of control service neighbors complete!"); } } @Override public void removeEndpointProfile(EndpointProfileDto endpointProfile) throws ControlServiceException { checkNeighbors(); byte[] endpointKeyHash = endpointProfile.getEndpointKeyHash(); this.endpointService.removeEndpointProfileByKeyHash(endpointKeyHash); ApplicationDto appDto = getApplication(endpointProfile.getApplicationId()); ThriftEndpointDeregistrationMessage nf = new ThriftEndpointDeregistrationMessage(); nf.setAddress( new ThriftEntityAddress( appDto.getTenantId(), appDto.getApplicationToken(), ThriftClusterEntityType.ENDPOINT, ByteBuffer.wrap(endpointKeyHash) ) ); nf.setActorClassifier(ThriftActorClassifier.APPLICATION); neighbors.brodcastMessage(OperationsServiceMsg.fromDeregistration(nf)); } @Override public CredentialsDto provisionCredentials(String applicationId, String credentialsBody) throws ControlServiceException { CredentialsDto credentials = new CredentialsDto( Base64Utils.decodeFromString(credentialsBody), CredentialsStatus.AVAILABLE); try { return this.credentialsServiceLocator .getCredentialsService(applicationId) .provideCredentials(credentials); } catch (CredentialsServiceException cause) { String message = MessageFormat .format("An unexpected exception occured while saving credentials [{0}]", credentials); LOG.error(message, cause); throw new ControlServiceException(cause); } } @Override public Optional<CredentialsDto> getCredentials(String applicationId, String credentialsId) throws ControlServiceException { try { return this.credentialsServiceLocator .getCredentialsService(applicationId) .lookupCredentials(credentialsId); } catch (CredentialsServiceException cause) { String message = MessageFormat .format("An unexpected exception occured while searching for credentials by ID [{0}]", credentialsId); LOG.error(message, cause); throw new ControlServiceException(cause); } } @Override public void revokeCredentials(String applicationId, String credentialsId) throws ControlServiceException { try { this.credentialsServiceLocator .getCredentialsService(applicationId) .markCredentialsRevoked(credentialsId); onCredentailsRevoked(applicationId, credentialsId); } catch (CredentialsServiceException cause) { String message = MessageFormat .format("An unexpected exception occured while revoking credentials by ID [{0}]", credentialsId); LOG.error(message, cause); throw new ControlServiceException(cause); } } @Override public void onCredentailsRevoked(String applicationId, String credentialsId) throws ControlServiceException { LOG.debug("[{}] Lookup registration information based on credentials ID [{}]", applicationId, credentialsId); try { Optional<EndpointRegistrationDto> endpointRegistrationOptional = endpointRegistrationService .findEndpointRegistrationByCredentialsId(credentialsId); if (endpointRegistrationOptional.isPresent()) { EndpointRegistrationDto endpointRegistration = endpointRegistrationOptional.get(); LOG.debug("[{}] Found endpoint registration information [{}]", applicationId, endpointRegistration); if (endpointRegistration.getEndpointId() != null) { checkNeighbors(); ApplicationDto appDto = getApplication(endpointRegistration.getApplicationId()); ThriftEndpointDeregistrationMessage nf = new ThriftEndpointDeregistrationMessage(); nf.setAddress( new ThriftEntityAddress( appDto.getTenantId(), appDto.getApplicationToken(), ThriftClusterEntityType.ENDPOINT, ByteBuffer.wrap(Base64Util.decode(endpointRegistration.getEndpointId())) ) ); nf.setActorClassifier(ThriftActorClassifier.APPLICATION); neighbors.brodcastMessage(OperationsServiceMsg.fromDeregistration(nf)); } endpointRegistrationService.removeEndpointRegistrationById(endpointRegistration.getId()); LOG.debug("[{}] endpoint registration information [{}] removed", applicationId, endpointRegistration); } else { LOG.debug("[{}] No endpoint registration information provisioned for credentials ID [{}]", applicationId, credentialsId); } } catch (EndpointRegistrationServiceException cause) { String message = MessageFormat .format("An unexpected exception occured while " + "lookup registration information based on credentails ID [{0}]", credentialsId); LOG.error(message, cause); throw new ControlServiceException(cause); } } @Override public void provisionRegistration( String applicationId, String credentialsId, Integer serverProfileVersion, String serverProfileBody) throws ControlServiceException { EndpointRegistrationDto endpointRegistration = new EndpointRegistrationDto( applicationId, null, credentialsId, serverProfileVersion, serverProfileBody); try { this.endpointRegistrationService.saveEndpointRegistration(endpointRegistration); } catch (EndpointRegistrationServiceException cause) { String message = MessageFormat .format("An unexpected exception occured while saving endpoint registration [{0}]", endpointRegistration); LOG.error(message, cause); throw new ControlServiceException(cause); } } @Override public List<String> getCredentialsServiceNames() throws ControlServiceException { return this.credentialsServiceRegistry.getCredentialsServiceNames(); } @Override public EndpointUserConfigurationDto findUserConfigurationByExternalUIdAndAppTokenAndSchemaVersion( String externalUId, String appToken, Integer schemaVersion, String tenantId) { return userConfigurationService.findUserConfigurationByExternalUIdAndAppTokenAndSchemaVersion( externalUId, appToken, schemaVersion, tenantId); } @Override public String findEndpointConfigurationByEndpointKeyHash(String endpointKeyHash) throws KaaAdminServiceException { EndpointProfileDto endpointProfileDto = profileService .findEndpointProfileByEndpointKeyHash(endpointKeyHash); ConfigurationSchemaDto configurationSchemaDto = configurationService .findConfSchemaByAppIdAndVersion( endpointProfileDto.getApplicationId(), endpointProfileDto.getConfigurationVersion() ); CTLSchemaDto ctlSchemaDto = ctlService .findCtlSchemaById(configurationSchemaDto.getCtlSchemaId()); String schema = ctlService.flatExportAsString(ctlSchemaDto); String endConf = null; String appToken; try { appToken = applicationService .findAppById(endpointProfileDto.getApplicationId()) .getApplicationToken(); byte[] config = deltaService .getConfiguration(appToken, Base64Util.encode(endpointProfileDto.getEndpointKeyHash()), endpointProfileDto) .getConfiguration(); endConf = GenericAvroConverter.toJson(config, schema); } catch (GetDeltaException ex) { LOG.error("Could not retrieve configuration!"); Utils.handleException( new KaaAdminServiceException( "Could not retrieve configuration!!", ServiceErrorCode.INVALID_SCHEMA )); } return endConf; } @Override public Schema findEndpointConfigurationSchemaByEndpointKeyHash(String endpointKeyHash) throws KaaAdminServiceException { EndpointProfileDto endpointProfileDto = profileService .findEndpointProfileByEndpointKeyHash(endpointKeyHash); ConfigurationSchemaDto configurationSchemaDto = configurationService .findConfSchemaByAppIdAndVersion( endpointProfileDto.getApplicationId(), endpointProfileDto.getConfigurationVersion() ); CTLSchemaDto ctlSchemaDto = ctlService .findCtlSchemaById(configurationSchemaDto.getCtlSchemaId()); return ctlService.flatExportAsSchema(ctlSchemaDto); } @Override public ConfigurationSchemaDto findConfSchemaByAppIdAndVersion(String applicationId, int version) { return configurationService.findConfSchemaByAppIdAndVersion(applicationId, version); } }