|
|
|
@ -26,13 +26,15 @@ import org.wso2.carbon.apimgt.api.APIProvider;
|
|
|
|
|
import org.wso2.carbon.apimgt.api.FaultGatewaysException;
|
|
|
|
|
import org.wso2.carbon.apimgt.api.model.API;
|
|
|
|
|
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
|
|
|
|
|
import org.wso2.carbon.apimgt.api.model.APIStatus;
|
|
|
|
|
import org.wso2.carbon.apimgt.api.model.URITemplate;
|
|
|
|
|
import org.wso2.carbon.apimgt.impl.APIManagerFactory;
|
|
|
|
|
import org.wso2.carbon.apimgt.webapp.publisher.exception.APIPublisherException;
|
|
|
|
|
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
|
|
|
|
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
|
|
|
import org.wso2.carbon.governance.lcm.util.CommonUtil;
|
|
|
|
|
import org.wso2.carbon.registry.core.exceptions.RegistryException;
|
|
|
|
|
import org.wso2.carbon.registry.core.service.RegistryService;
|
|
|
|
|
import org.wso2.carbon.user.api.UserStoreException;
|
|
|
|
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
|
|
|
|
|
|
|
|
|
import javax.xml.stream.XMLStreamException;
|
|
|
|
@ -41,7 +43,6 @@ import java.util.HashMap;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This class represents the concrete implementation of the APIPublisherService that corresponds to providing all
|
|
|
|
@ -50,89 +51,134 @@ import java.util.Set;
|
|
|
|
|
public class APIPublisherServiceImpl implements APIPublisherService {
|
|
|
|
|
|
|
|
|
|
private static final Log log = LogFactory.getLog(APIPublisherServiceImpl.class);
|
|
|
|
|
private static final String PUBLISH_ACTION = "Publish";
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void publishAPI(API api) throws APIManagementException, FaultGatewaysException {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Publishing API '" + api.getId() + "'");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
String tenantDomain = MultitenantUtils.getTenantDomain(api.getApiOwner());
|
|
|
|
|
int tenantId =
|
|
|
|
|
APIPublisherDataHolder.getInstance().getRealmService().getTenantManager().getTenantId(tenantDomain);
|
|
|
|
|
// Below code snippet is added load API Lifecycle in tenant mode, where in it does not load when tenant is loaded.
|
|
|
|
|
RegistryService registryService = APIPublisherDataHolder.getInstance().getRegistryService();
|
|
|
|
|
CommonUtil.addDefaultLifecyclesIfNotAvailable(registryService.getConfigSystemRegistry(tenantId),
|
|
|
|
|
CommonUtil.getRootSystemRegistry(tenantId));
|
|
|
|
|
APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(api.getApiOwner());
|
|
|
|
|
MultitenantUtils.getTenantDomain(api.getApiOwner());
|
|
|
|
|
if (provider != null) {
|
|
|
|
|
if (provider.isDuplicateContextTemplate(api.getContext())) {
|
|
|
|
|
throw new APIManagementException("Error occurred while adding the API. A duplicate API" +
|
|
|
|
|
" context already exists for " + api.getContext());
|
|
|
|
|
}
|
|
|
|
|
if (!provider.isAPIAvailable(api.getId())) {
|
|
|
|
|
provider.addAPI(api);
|
|
|
|
|
log.info("Successfully published API '" + api.getId().getApiName() + "' with context '" +
|
|
|
|
|
api.getContext() + "' and version '" + api.getId().getVersion() + "'");
|
|
|
|
|
} else {
|
|
|
|
|
provider.updateAPI(api);
|
|
|
|
|
log.info("An API already exists with the name '" + api.getId().getApiName() + "', context '" +
|
|
|
|
|
api.getContext() + "' and version '" + api.getId().getVersion() +
|
|
|
|
|
"'. Thus, the API config is updated");
|
|
|
|
|
}
|
|
|
|
|
provider.saveSwagger20Definition(api.getId(), createSwaggerDefinition(api));
|
|
|
|
|
} else {
|
|
|
|
|
throw new APIManagementException("API provider configured for the given API configuration is null. " +
|
|
|
|
|
"Thus, the API is not published");
|
|
|
|
|
}
|
|
|
|
|
} catch (UserStoreException e) {
|
|
|
|
|
throw new APIManagementException("Failed to get the tenant id for the user " + api.getApiOwner(), e);
|
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
|
throw new APIManagementException("Failed to retrieve life cycle file ", e);
|
|
|
|
|
} catch (RegistryException e) {
|
|
|
|
|
throw new APIManagementException("Failed to access the registry ", e);
|
|
|
|
|
} catch (XMLStreamException e) {
|
|
|
|
|
throw new APIManagementException("Failed parsing the lifecycle xml.", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public void publishAPI(final API api) throws APIManagementException, FaultGatewaysException {
|
|
|
|
|
// A thread is initialized because we cannot guarantee that the gateway is initialized before publishing.
|
|
|
|
|
// A better solution is needs to be implemented - should check in apimanager whether
|
|
|
|
|
// the gateway is local and if so then publish it through OSGI
|
|
|
|
|
Runnable connector = new Runnable() {
|
|
|
|
|
public void run() {
|
|
|
|
|
if (waitForServerStartup()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Publishing API '" + api.getId() + "");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
Thread.interrupted();
|
|
|
|
|
}
|
|
|
|
|
synchronized (APIPublisherServiceImpl.class) {
|
|
|
|
|
String tenantDomain = MultitenantUtils.getTenantDomain(api.getApiOwner());
|
|
|
|
|
PrivilegedCarbonContext.startTenantFlow();
|
|
|
|
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
|
|
|
|
|
try {
|
|
|
|
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
|
|
|
|
// Below code snippet is added to load API Lifecycle in tenant mode.
|
|
|
|
|
RegistryService registryService = APIPublisherDataHolder.getInstance().getRegistryService();
|
|
|
|
|
CommonUtil.addDefaultLifecyclesIfNotAvailable(registryService.getConfigSystemRegistry(tenantId),
|
|
|
|
|
CommonUtil.getRootSystemRegistry(tenantId));
|
|
|
|
|
APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(api.getApiOwner());
|
|
|
|
|
MultitenantUtils.getTenantDomain(api.getApiOwner());
|
|
|
|
|
if (provider != null) {
|
|
|
|
|
if (provider.isDuplicateContextTemplate(api.getContext())) {
|
|
|
|
|
throw new APIManagementException(
|
|
|
|
|
"Error occurred while adding the API. A duplicate API" +
|
|
|
|
|
" context already exists for " + api.getContext());
|
|
|
|
|
}
|
|
|
|
|
if (!provider.isAPIAvailable(api.getId())) {
|
|
|
|
|
provider.addAPI(api);
|
|
|
|
|
provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION);
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("Successfully published API '" + api.getId().getApiName() +
|
|
|
|
|
"' with context '" + api.getContext() + "' and version '"
|
|
|
|
|
+ api.getId().getVersion() + "'");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
api.setStatus(APIStatus.PUBLISHED);
|
|
|
|
|
provider.updateAPI(api);
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
log.debug("An API already exists with the name '" + api.getId().getApiName() +
|
|
|
|
|
"', context '" + api.getContext() + "' and version '"
|
|
|
|
|
+ api.getId().getVersion() + "'. Thus, the API config is updated");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
provider.saveSwagger20Definition(api.getId(), createSwaggerDefinition(api));
|
|
|
|
|
} else {
|
|
|
|
|
throw new APIManagementException("API provider configured for the given API configuration " +
|
|
|
|
|
"is null. Thus, the API is not published");
|
|
|
|
|
}
|
|
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
|
throw new APIPublisherException("Failed to retrieve life cycle file ", e);
|
|
|
|
|
} catch (RegistryException e) {
|
|
|
|
|
throw new APIPublisherException("Failed to access the registry ", e);
|
|
|
|
|
} catch (XMLStreamException e) {
|
|
|
|
|
throw new APIPublisherException("Failed parsing the lifecycle xml.", e);
|
|
|
|
|
} catch (FaultGatewaysException e) {
|
|
|
|
|
throw new APIPublisherException("Failed when publishing to the gateway", e);
|
|
|
|
|
} catch (APIManagementException e) {
|
|
|
|
|
throw new APIPublisherException("Failed publishing the API " + api.getId().getApiName(), e);
|
|
|
|
|
} finally {
|
|
|
|
|
PrivilegedCarbonContext.endTenantFlow();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
Thread connectorThread = new Thread(connector);
|
|
|
|
|
connectorThread.setDaemon(true);
|
|
|
|
|
connectorThread.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String createSwaggerDefinition(API api) {
|
|
|
|
|
Map<String, JsonObject> httpVerbsMap = new HashMap<>();
|
|
|
|
|
private boolean waitForServerStartup() {
|
|
|
|
|
while (!APIPublisherDataHolder.getInstance().getServerStartupListener().isServerReady()) {
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
Thread.interrupted();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (URITemplate uriTemplate : api.getUriTemplates()) {
|
|
|
|
|
JsonObject response = new JsonObject();
|
|
|
|
|
response.addProperty("200", "");
|
|
|
|
|
private String createSwaggerDefinition(API api) {
|
|
|
|
|
Map<String, JsonObject> httpVerbsMap = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
JsonObject responses = new JsonObject();
|
|
|
|
|
responses.add("responses", response);
|
|
|
|
|
JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate());
|
|
|
|
|
if (httpVerbs == null) {
|
|
|
|
|
httpVerbs = new JsonObject();
|
|
|
|
|
}
|
|
|
|
|
httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), responses);
|
|
|
|
|
httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs);
|
|
|
|
|
}
|
|
|
|
|
for (URITemplate uriTemplate : api.getUriTemplates()) {
|
|
|
|
|
JsonObject response = new JsonObject();
|
|
|
|
|
response.addProperty("200", "");
|
|
|
|
|
|
|
|
|
|
Iterator it = httpVerbsMap.entrySet().iterator();
|
|
|
|
|
JsonObject paths = new JsonObject();
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
Map.Entry<String, JsonObject> pair = (Map.Entry)it.next();
|
|
|
|
|
paths.add(pair.getKey(), pair.getValue());
|
|
|
|
|
it.remove();
|
|
|
|
|
}
|
|
|
|
|
JsonObject responses = new JsonObject();
|
|
|
|
|
responses.add("responses", response);
|
|
|
|
|
JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate());
|
|
|
|
|
if (httpVerbs == null) {
|
|
|
|
|
httpVerbs = new JsonObject();
|
|
|
|
|
}
|
|
|
|
|
httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), responses);
|
|
|
|
|
httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JsonObject info = new JsonObject();
|
|
|
|
|
info.addProperty("title", api.getId().getApiName());
|
|
|
|
|
info.addProperty("version", api.getId().getVersion());
|
|
|
|
|
Iterator it = httpVerbsMap.entrySet().iterator();
|
|
|
|
|
JsonObject paths = new JsonObject();
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
Map.Entry<String, JsonObject> pair = (Map.Entry) it.next();
|
|
|
|
|
paths.add(pair.getKey(), pair.getValue());
|
|
|
|
|
it.remove();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JsonObject swaggerDefinition = new JsonObject();
|
|
|
|
|
swaggerDefinition.add("paths", paths);
|
|
|
|
|
swaggerDefinition.addProperty("swagger", "2.0");
|
|
|
|
|
swaggerDefinition.add("info", info);
|
|
|
|
|
JsonObject info = new JsonObject();
|
|
|
|
|
info.addProperty("title", api.getId().getApiName());
|
|
|
|
|
info.addProperty("version", api.getId().getVersion());
|
|
|
|
|
|
|
|
|
|
return swaggerDefinition.toString();
|
|
|
|
|
}
|
|
|
|
|
JsonObject swaggerDefinition = new JsonObject();
|
|
|
|
|
swaggerDefinition.add("paths", paths);
|
|
|
|
|
swaggerDefinition.addProperty("swagger", "2.0");
|
|
|
|
|
swaggerDefinition.add("info", info);
|
|
|
|
|
|
|
|
|
|
return swaggerDefinition.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void removeAPI(APIIdentifier id) throws APIManagementException {
|
|
|
|
|