diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java index 8213d3ca76..bff1b080ec 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -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 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 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 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 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 { diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java index 2a502825ad..9ae9340513 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java @@ -37,6 +37,7 @@ public class APIPublisherUtil { private static final String DEFAULT_API_VERSION = "1.0.0"; public static final String API_VERSION_PARAM="{version}"; + public static final String API_PUBLISH_ENVIRONEMENT = "Production and Sandbox"; enum HTTPMethod { GET, POST, DELETE, PUT, OPTIONS @@ -75,10 +76,13 @@ public class APIPublisherUtil { api.setUrl(config.getEndpoint()); api.addAvailableTiers(provider.getTiers()); api.setEndpointSecured(true); - api.setStatus(APIStatus.PUBLISHED); + api.setStatus(APIStatus.CREATED); api.setTransports(config.getTransports()); api.setContextTemplate(config.getContextTemplate()); api.setUriTemplates(config.getUriTemplates()); + Set environements = new HashSet<>(); + environements.add(API_PUBLISH_ENVIRONEMENT); + api.setEnvironments(environements); Set tiers = new HashSet(); tiers.add(new Tier(APIConstants.UNLIMITED_TIER)); api.addAvailableTiers(tiers); @@ -91,7 +95,7 @@ public class APIPublisherUtil { } api.setResponseCache(APIConstants.DISABLED); - String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + "\",\"config\":null},\"endpoint_type\":\"http\"}"; + String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}"; api.setEndpointConfig(endpointConfig); if ("".equals(id.getVersion()) || (DEFAULT_API_VERSION.equals(id.getVersion()))) { diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIPublisherException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIPublisherException.java new file mode 100644 index 0000000000..e5c7b58596 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIPublisherException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.webapp.publisher.exception; + + +public class APIPublisherException extends RuntimeException { + + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public APIPublisherException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public APIPublisherException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public APIPublisherException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public APIPublisherException() { + super(); + } + + public APIPublisherException(Throwable cause) { + super(cause); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java index bd291ce3be..7f220209b6 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java @@ -20,6 +20,8 @@ package org.wso2.carbon.apimgt.webapp.publisher.internal; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; +import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.ServerStartupListener; +import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.tenant.TenantManager; @@ -32,6 +34,7 @@ public class APIPublisherDataHolder { private RealmService realmService; private TenantManager tenantManager; private RegistryService registryService; + private ServerStartupListener serverStartupListener; private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder(); @@ -94,4 +97,12 @@ public class APIPublisherDataHolder { public void setRegistryService(RegistryService registryService) { this.registryService = registryService; } + + public ServerStartupListener getServerStartupListener() { + return serverStartupListener; + } + + public void setServerStartupListener(ServerStartupListener serverStartupListener) { + this.serverStartupListener = serverStartupListener; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java index 10a20d9a48..db84a863aa 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java @@ -25,6 +25,8 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherServiceImpl; +import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.ServerStartupListener; +import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.ConfigurationContextService; @@ -59,7 +61,10 @@ public class APIPublisherServiceComponent { if (log.isDebugEnabled()) { log.debug("Initializing device management core bundle"); } - + BundleContext bundleContext = componentContext.getBundleContext(); + ServerStartupListener serverStartupListener = new ServerStartupListener(); + bundleContext.registerService(ServerStartupObserver.class.getName(), serverStartupListener, null); + APIPublisherDataHolder.getInstance().setServerStartupListener(serverStartupListener); /* Registering declarative service instances exposed by DeviceManagementServiceComponent */ this.registerServices(componentContext); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java index 9e47ce2939..0b4a3cff91 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java @@ -25,6 +25,7 @@ import org.apache.catalina.core.StandardContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.apimgt.api.model.*; +import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.webapp.publisher.*; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; @@ -47,14 +48,12 @@ public class APIPublisherLifecycleListener implements LifecycleListener { private static final String PARAM_MANAGED_API_VERSION = "managed-api-version"; private static final String PARAM_MANAGED_API_CONTEXT = "managed-api-context"; private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint"; - private static final String PARAM_MANAGED_API_ENDPOINT_CONTEXT = "managed-api-endpoint-context"; private static final String PARAM_MANAGED_API_OWNER = "managed-api-owner"; private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports"; private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured"; private static final String PARAM_MANAGED_API_APPLICATION = "managed-api-application"; private static final String PARAM_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants"; private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain"; - private static final String VERSION_PLACEHOLDER = "{version}"; private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class); @Override @@ -70,7 +69,7 @@ public class APIPublisherLifecycleListener implements LifecycleListener { AnnotationUtil annotationUtil = new AnnotationUtil(context); Set annotatedAPIClasses = annotationUtil. scanStandardContext(org.wso2.carbon.apimgt.annotations.api.API.class.getName()); - List apiDefinitions = annotationUtil.extractAPIInfo(annotatedAPIClasses); + List apiDefinitions = annotationUtil.extractAPIInfo(servletContext, annotatedAPIClasses); for (APIResourceConfiguration apiDefinition : apiDefinitions) { APIConfig apiConfig = this.buildApiConfig(servletContext, apiDefinition); @@ -161,9 +160,9 @@ public class APIPublisherLifecycleListener implements LifecycleListener { tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain : MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; apiConfig.setTenantDomain(tenantDomain); - String contextTemplate = context + "/" + VERSION_PLACEHOLDER; + String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER; if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { - contextTemplate = context + "/t/" + tenantDomain + "/" + VERSION_PLACEHOLDER; + contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER; } apiConfig.setContextTemplate(contextTemplate); @@ -172,13 +171,8 @@ public class APIPublisherLifecycleListener implements LifecycleListener { if (log.isDebugEnabled()) { log.debug("'managed-api-endpoint' attribute is not configured"); } - String endpointContext = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT_CONTEXT); - if (endpointContext != null && !endpointContext.isEmpty()) { - endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); - } else { - endpoint = APIPublisherUtil.getApiEndpointUrl(context); - } - + String endpointContext = servletContext.getContextPath(); + endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); } apiConfig.setEndpoint(endpoint); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java index 31372e70c3..a26c2042f1 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java @@ -92,7 +92,7 @@ public class AnnotationUtil { * @param entityClasses * @return */ - public List extractAPIInfo(Set entityClasses) + public List extractAPIInfo(final ServletContext servletContext, Set entityClasses) throws ClassNotFoundException { List apiResourceConfigs = new ArrayList(); @@ -111,7 +111,7 @@ public class AnnotationUtil { classLoader.loadClass(org.wso2.carbon.apimgt.annotations.api.API.class.getName()); Annotation apiAnno = clazz.getAnnotation(apiClazz); - List resourceList = null; + List resourceList; apiResourceConfig = new APIResourceConfiguration(); if (apiAnno != null) { @@ -139,21 +139,27 @@ public class AnnotationUtil { break; } } - - String rootContext = ""; + // All the apis should map to same root "/" + String rootContext = servletContext.getContextPath(); pathClazz = (Class) classLoader.loadClass(Path.class.getName()); pathClazzMethods = pathClazz.getMethods(); Annotation rootContectAnno = clazz.getAnnotation(pathClazz); + String subContext = ""; if (rootContectAnno != null) { - rootContext = invokeMethod(pathClazzMethods[0], rootContectAnno, STRING); + subContext = invokeMethod(pathClazzMethods[0], rootContectAnno, STRING); + if (subContext != null && !subContext.isEmpty()) { + rootContext = rootContext + "/" + subContext; + } else { + subContext = ""; + } if (log.isDebugEnabled()) { log.debug("API Root Context = " + rootContext); } } Method[] annotatedMethods = clazz.getDeclaredMethods(); - resourceList = getApiResources(rootContext, annotatedMethods); + resourceList = getApiResources(rootContext, subContext, annotatedMethods); apiResourceConfig.setResources(resourceList); } catch (Throwable throwable) { log.error("Error encountered while scanning for annotations", throwable); @@ -171,7 +177,7 @@ public class AnnotationUtil { return apiResourceConfigs; } - private List getApiResources(String rootContext, Method[] annotatedMethods) throws Throwable { + private List getApiResources(String resourceRootContext, String apiRootContext, Method[] annotatedMethods) throws Throwable { List resourceList; resourceList = new ArrayList(); for (Method method : annotatedMethods) { @@ -179,12 +185,13 @@ public class AnnotationUtil { if (methodContextAnno != null) { String subCtx = invokeMethod(pathClazzMethods[0], methodContextAnno, STRING); APIResource resource = new APIResource(); - resource.setUriTemplate(makeContextURLReady(subCtx)); + resource.setUriTemplate(makeContextURLReady(apiRootContext + subCtx)); String serverIP = System.getProperty(SERVER_HOST); String httpServerPort = System.getProperty(HTTP_PORT); - resource.setUri(PROTOCOL_HTTP + "://" + serverIP + ":" + httpServerPort + makeContextURLReady(rootContext) + makeContextURLReady(subCtx)); + resource.setUri(PROTOCOL_HTTP + "://" + serverIP + ":" + httpServerPort + makeContextURLReady( + resourceRootContext) + makeContextURLReady(subCtx)); resource.setAuthType(AUTH_TYPE); Annotation[] annotations = method.getDeclaredAnnotations(); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/ServerStartupListener.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/ServerStartupListener.java new file mode 100644 index 0000000000..c03b2379fd --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/ServerStartupListener.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util; + +import org.wso2.carbon.core.ServerStartupObserver; + +/** + * This is added to make sure that the apis are publishsed after gateway services are intiialized. + */ +public class ServerStartupListener implements ServerStartupObserver { + private static volatile boolean serverReady = false; + @Override + public void completingServerStartup() { + } + + @Override + public void completedServerStartup() { + ServerStartupListener.setServerReady(true); + } + + public static boolean isServerReady() { + return ServerStartupListener.serverReady; + } + + public static void setServerReady(boolean serverReady) { + ServerStartupListener.serverReady = serverReady; + } +}