|
|
|
@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.apimgt.webapp.publisher;
|
|
|
|
|
|
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
|
|
|
|
|
import io.entgra.device.mgt.core.apimgt.webapp.publisher.dto.ApiScope;
|
|
|
|
|
import io.entgra.device.mgt.core.apimgt.webapp.publisher.exception.APIManagerPublisherException;
|
|
|
|
|
import io.entgra.device.mgt.core.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
|
|
|
|
|
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException;
|
|
|
|
@ -34,20 +35,22 @@ import org.apache.commons.logging.Log;
|
|
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
|
import org.wso2.carbon.core.ServerStartupObserver;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Stack;
|
|
|
|
|
|
|
|
|
|
public class APIPublisherStartupHandler implements ServerStartupObserver {
|
|
|
|
|
|
|
|
|
|
private static final Log log = LogFactory.getLog(APIPublisherStartupHandler.class);
|
|
|
|
|
private static int retryTime = 2000;
|
|
|
|
|
private static final int CONNECTION_RETRY_FACTOR = 2;
|
|
|
|
|
private static final int MAX_RETRY_COUNT = 5;
|
|
|
|
|
private static Stack<APIConfig> failedAPIsStack = new Stack<>();
|
|
|
|
|
private static Stack<APIConfig> currentAPIsStack;
|
|
|
|
|
private static final Gson gson = new Gson();
|
|
|
|
|
|
|
|
|
|
private static final Stack<APIConfig> failedAPIsStack = new Stack<>();
|
|
|
|
|
private static int retryTime = 2000;
|
|
|
|
|
private static Stack<APIConfig> currentAPIsStack;
|
|
|
|
|
private final List<String> publishedAPIs = new ArrayList<>();
|
|
|
|
|
private APIPublisherService publisher;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -59,71 +62,87 @@ public class APIPublisherStartupHandler implements ServerStartupObserver {
|
|
|
|
|
public void completedServerStartup() {
|
|
|
|
|
APIPublisherDataHolder.getInstance().setServerStarted(true);
|
|
|
|
|
currentAPIsStack = APIPublisherDataHolder.getInstance().getUnpublishedApis();
|
|
|
|
|
Thread t = new Thread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Server has just started, hence started publishing unpublished APIs");
|
|
|
|
|
log.debug("Total number of unpublished APIs: "
|
|
|
|
|
+ APIPublisherDataHolder.getInstance().getUnpublishedApis().size());
|
|
|
|
|
}
|
|
|
|
|
publisher = APIPublisherDataHolder.getInstance().getApiPublisherService();
|
|
|
|
|
int retryCount = 0;
|
|
|
|
|
while (retryCount < MAX_RETRY_COUNT && (!failedAPIsStack.isEmpty() || !currentAPIsStack.isEmpty())) {
|
|
|
|
|
Thread t = new Thread(() -> {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Server has just started, hence started publishing unpublished APIs");
|
|
|
|
|
log.debug("Total number of unpublished APIs: "
|
|
|
|
|
+ APIPublisherDataHolder.getInstance().getUnpublishedApis().size());
|
|
|
|
|
}
|
|
|
|
|
publisher = APIPublisherDataHolder.getInstance().getApiPublisherService();
|
|
|
|
|
int retryCount = 0;
|
|
|
|
|
while (retryCount < MAX_RETRY_COUNT && (!failedAPIsStack.isEmpty() || !currentAPIsStack.isEmpty())) {
|
|
|
|
|
if (retryCount > 0) {
|
|
|
|
|
try {
|
|
|
|
|
retryTime = retryTime * CONNECTION_RETRY_FACTOR;
|
|
|
|
|
Thread.sleep(retryTime);
|
|
|
|
|
} catch (InterruptedException te) {
|
|
|
|
|
//do nothing.
|
|
|
|
|
}
|
|
|
|
|
Stack<APIConfig> failedApis;
|
|
|
|
|
if (!APIPublisherDataHolder.getInstance().getUnpublishedApis().isEmpty()) {
|
|
|
|
|
publishAPIs(currentAPIsStack, failedAPIsStack);
|
|
|
|
|
failedApis = failedAPIsStack;
|
|
|
|
|
} else {
|
|
|
|
|
publishAPIs(failedAPIsStack, currentAPIsStack);
|
|
|
|
|
failedApis = currentAPIsStack;
|
|
|
|
|
}
|
|
|
|
|
retryCount++;
|
|
|
|
|
if (retryCount == MAX_RETRY_COUNT && !failedApis.isEmpty()) {
|
|
|
|
|
StringBuilder error = new StringBuilder();
|
|
|
|
|
error.append("Error occurred while publishing API ['");
|
|
|
|
|
while (!failedApis.isEmpty()) {
|
|
|
|
|
APIConfig api = failedApis.pop();
|
|
|
|
|
error.append(api.getName() + ",");
|
|
|
|
|
}
|
|
|
|
|
error.append("']");
|
|
|
|
|
log.error(error.toString());
|
|
|
|
|
}
|
|
|
|
|
Stack<APIConfig> failedApis;
|
|
|
|
|
if (!currentAPIsStack.isEmpty()) {
|
|
|
|
|
publishAPIs(currentAPIsStack, failedAPIsStack);
|
|
|
|
|
failedApis = failedAPIsStack;
|
|
|
|
|
} else {
|
|
|
|
|
publishAPIs(failedAPIsStack, currentAPIsStack);
|
|
|
|
|
failedApis = currentAPIsStack;
|
|
|
|
|
}
|
|
|
|
|
retryCount++;
|
|
|
|
|
if (retryCount == MAX_RETRY_COUNT && !failedApis.isEmpty()) {
|
|
|
|
|
StringBuilder error = new StringBuilder();
|
|
|
|
|
error.append("Error occurred while publishing API ['");
|
|
|
|
|
while (!failedApis.isEmpty()) {
|
|
|
|
|
APIConfig api = failedApis.pop();
|
|
|
|
|
error.append(api.getName() + ",");
|
|
|
|
|
}
|
|
|
|
|
error.append("']");
|
|
|
|
|
log.info(error.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
publisher.updateScopeRoleMapping();
|
|
|
|
|
publisher.addDefaultScopesIfNotExist();
|
|
|
|
|
} catch (APIManagerPublisherException e) {
|
|
|
|
|
log.error("failed to update scope role mapping.", e);
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
publisher.updateScopeRoleMapping();
|
|
|
|
|
publisher.addDefaultScopesIfNotExist();
|
|
|
|
|
} catch (APIManagerPublisherException e) {
|
|
|
|
|
log.error("failed to update scope role mapping.", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateScopeMetadataEntryWithDefaultScopes();
|
|
|
|
|
updateScopeMetadataEntryWithDefaultScopes();
|
|
|
|
|
log.info("Successfully published : [" + publishedAPIs + "]. " +
|
|
|
|
|
"and failed : [" + failedAPIsStack + "] " +
|
|
|
|
|
"Total successful count : [" + publishedAPIs.size() + "]. " +
|
|
|
|
|
"Failed count : [" + failedAPIsStack.size() + "]");
|
|
|
|
|
|
|
|
|
|
// execute after api publishing
|
|
|
|
|
for (PostApiPublishingObsever observer : APIPublisherDataHolder.getInstance().getPostApiPublishingObseverList()) {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Executing " + observer.getClass().getName());
|
|
|
|
|
}
|
|
|
|
|
observer.execute();
|
|
|
|
|
// execute after api publishing
|
|
|
|
|
for (PostApiPublishingObsever observer : APIPublisherDataHolder.getInstance().getPostApiPublishingObseverList()) {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Executing " + observer.getClass().getName());
|
|
|
|
|
}
|
|
|
|
|
log.info("Finish executing PostApiPublishingObsevers");
|
|
|
|
|
observer.execute();
|
|
|
|
|
}
|
|
|
|
|
log.info("Finish executing PostApiPublishingObsevers");
|
|
|
|
|
});
|
|
|
|
|
t.start();
|
|
|
|
|
log.info("Starting API publishing procedure");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Publish apis provided by the API stack, if failed while publishing, then failed API will be added to
|
|
|
|
|
* the failed API stack
|
|
|
|
|
*
|
|
|
|
|
* @param apis Stack of APIs to publish
|
|
|
|
|
* @param failedStack Stack to record failed APIs
|
|
|
|
|
*/
|
|
|
|
|
private void publishAPIs(Stack<APIConfig> apis, Stack<APIConfig> failedStack) {
|
|
|
|
|
while (!apis.isEmpty()) {
|
|
|
|
|
APIConfig api = apis.pop();
|
|
|
|
|
try {
|
|
|
|
|
publisher.publishAPI(api);
|
|
|
|
|
for (ApiScope scope : api.getScopes()) {
|
|
|
|
|
APIPublisherDataHolder.getInstance().getPermScopeMapping().putIfAbsent(scope.getPermissions(), scope.getKey());
|
|
|
|
|
}
|
|
|
|
|
publishedAPIs.add(api.getName());
|
|
|
|
|
log.info("Successfully published API [" + api.getName() + "]");
|
|
|
|
|
} catch (APIManagerPublisherException e) {
|
|
|
|
|
log.error("failed to publish api.", e);
|
|
|
|
|
failedStack.push(api);
|
|
|
|
@ -136,34 +155,42 @@ public class APIPublisherStartupHandler implements ServerStartupObserver {
|
|
|
|
|
* will create that entry and update the value with default permissions.
|
|
|
|
|
*/
|
|
|
|
|
private void updateScopeMetadataEntryWithDefaultScopes() {
|
|
|
|
|
Map<String, String> permScopeMap = APIPublisherDataHolder.getInstance().getPermScopeMapping();
|
|
|
|
|
Metadata permScopeMapping;
|
|
|
|
|
|
|
|
|
|
MetadataManagementService metadataManagementService = APIPublisherDataHolder.getInstance().getMetadataManagementService();
|
|
|
|
|
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
|
|
|
|
|
DefaultPermissions defaultPermissions = deviceManagementConfig.getDefaultPermissions();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
|
|
|
|
|
DefaultPermissions defaultPermissions = deviceManagementConfig.getDefaultPermissions();
|
|
|
|
|
Metadata permScopeMapping = metadataManagementService.retrieveMetadata(Constants.PERM_SCOPE_MAPPING_META_KEY);
|
|
|
|
|
Map<String, String> permScopeMap = (permScopeMapping != null) ? gson.fromJson(permScopeMapping.getMetaValue(), HashMap.class) :
|
|
|
|
|
new HashMap<>();
|
|
|
|
|
for (DefaultPermission defaultPermission : defaultPermissions.getDefaultPermissions()) {
|
|
|
|
|
permScopeMap.putIfAbsent(defaultPermission.getName(),
|
|
|
|
|
defaultPermission.getScopeMapping().getKey());
|
|
|
|
|
permScopeMapping = metadataManagementService.retrieveMetadata(Constants.PERM_SCOPE_MAPPING_META_KEY);
|
|
|
|
|
boolean entryAlreadyExists = permScopeMapping != null;
|
|
|
|
|
if (permScopeMap == null || permScopeMap.isEmpty()) {
|
|
|
|
|
permScopeMap = entryAlreadyExists ? gson.fromJson(permScopeMapping.getMetaValue(), HashMap.class) :
|
|
|
|
|
new HashMap<>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APIPublisherDataHolder.getInstance().setPermScopeMapping(permScopeMap);
|
|
|
|
|
if (permScopeMapping != null) {
|
|
|
|
|
permScopeMapping.setMetaValue(gson.toJson(permScopeMap));
|
|
|
|
|
metadataManagementService.updateMetadata(permScopeMapping);
|
|
|
|
|
return;
|
|
|
|
|
for (DefaultPermission defaultPermission : defaultPermissions.getDefaultPermissions()) {
|
|
|
|
|
permScopeMap.putIfAbsent(defaultPermission.getName(), defaultPermission.getScopeMapping().getKey());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
permScopeMapping = new Metadata();
|
|
|
|
|
permScopeMapping.setMetaKey(Constants.PERM_SCOPE_MAPPING_META_KEY);
|
|
|
|
|
permScopeMapping.setMetaValue(gson.toJson(permScopeMap));
|
|
|
|
|
metadataManagementService.createMetadata(permScopeMapping);
|
|
|
|
|
|
|
|
|
|
if (entryAlreadyExists) {
|
|
|
|
|
metadataManagementService.updateMetadata(permScopeMapping);
|
|
|
|
|
} else {
|
|
|
|
|
metadataManagementService.createMetadata(permScopeMapping);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APIPublisherDataHolder.getInstance().setPermScopeMapping(permScopeMap);
|
|
|
|
|
log.info(Constants.PERM_SCOPE_MAPPING_META_KEY + "entry updated successfully");
|
|
|
|
|
} catch (MetadataManagementException e) {
|
|
|
|
|
log.error("Error encountered while updating permission scope mapping metadata with default scopes");
|
|
|
|
|
} catch (MetadataKeyAlreadyExistsException e) {
|
|
|
|
|
log.error("Metadata entry already exists for " + Constants.PERM_SCOPE_MAPPING_META_KEY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|