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