/*
* 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.governance.registry.extensions.executors.apistore;
import org.apache.axiom.om.OMElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.generic.GenericArtifactManager;
import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact;
import org.wso2.carbon.governance.registry.extensions.executors.utils.ExecutorConstants;
import org.wso2.carbon.governance.registry.extensions.interfaces.Execution;
import org.wso2.carbon.governance.registry.extensions.internal.GovernanceRegistryExtensionsComponent;
import org.wso2.carbon.governance.registry.extensions.internal.GovernanceRegistryExtensionsDataHolder;
import org.wso2.carbon.governance.registry.extensions.utils.APIUtils;
import org.wso2.carbon.governance.registry.extensions.utils.Constants;
import org.wso2.carbon.governance.registry.extensions.utils.ResponseAPIM;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext;
import org.wso2.securevault.SecretResolver;
import org.wso2.securevault.SecretResolverFactory;
import org.wso2.carbon.registry.core.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.wso2.carbon.governance.registry.extensions.executors.utils.ExecutorConstants.*;
/**
* This class will be used for publishing services as apis to APIM through publisher apis.
* This will be invoked in promote transitions.
*/
public class ServiceToAPIExecutor implements Execution {
private static final Log LOG = LogFactory.getLog(ServiceToAPIExecutor.class);
private String soapServiceMediaType = "application/vnd.wso2-soap-service+xml";
private String apimEndpoint = null;
private String apimUsername = null;
private String apimPassword = null;
private String defaultTier = "Unlimited";
private String apimEnv = null;
private String apiThrottlingTier = "Unlimited,Unlimited,Unlimited,Unlimited,Unlimited";
private Registry registry;
private GenericArtifact artifact;
/**
* This method is called when the execution class is initialized.
* All the execution classes are initialized only once.
*
* @param parameterMap Static parameter map given by the user.
* These are the parameters that have been given in the
* lifecycle configuration as the parameters of the executor.
*/
@Override
public void init(Map parameterMap) {
SecretResolver secretResolver = SecretResolverFactory.create((OMElement) null, false);
// Retrieves the secured password as follows
secretResolver.init(GovernanceRegistryExtensionsComponent.getSecretCallbackHandlerService()
.getSecretCallbackHandler());
if (secretResolver.isInitialized()) {
apimUsername = secretResolver.resolve(APIM_USERNAME);
apimPassword = secretResolver.resolve(APIM_PASSWORD);
}
if (parameterMap.get(APIM_ENDPOINT) != null) {
apimEndpoint = parameterMap.get(APIM_ENDPOINT).toString();
}
if (parameterMap.get(APIM_USERNAME) != null) {
apimUsername = parameterMap.get(APIM_USERNAME).toString();
}
if (parameterMap.get(APIM_PASSWORD) != null) {
apimPassword = parameterMap.get(APIM_PASSWORD).toString();
}
if (parameterMap.get(Constants.APIM_ENV) != null) {
apimEnv = parameterMap.get(Constants.APIM_ENV).toString();
}
if (parameterMap.get(DEFAULT_TIER) != null) {
defaultTier = parameterMap.get(DEFAULT_TIER).toString();
}
if (parameterMap.get(THROTTLING_TIER) != null) {
apiThrottlingTier = parameterMap.get(THROTTLING_TIER).toString();
}
}
/**
* @param context The request context that was generated from the registry core.
* The request context contains the resource, resource PATH and other
* variables generated during the initial call.
* @param currentState The current lifecycle state.
* @param targetState The target lifecycle state.
* @return Returns whether the execution was successful or not.
*/
public boolean execute(RequestContext context, String currentState, String targetState) {
List<String> publishedEnvList = new ArrayList<String>();
List<String> failedEnvList = new ArrayList<String>();
Resource resource = context.getResource();
String apiName;
try {
String user = CarbonContext.getThreadLocalCarbonContext().getUsername();
registry= GovernanceRegistryExtensionsDataHolder.getInstance().getRegistryService().getGovernanceUserRegistry(user,CarbonContext.getThreadLocalCarbonContext().getTenantId());
String artifactAbsolutePath = resource.getPath();
String artifactRelativePath=artifactAbsolutePath.substring("/_system/governance".length());
Resource apiArtifact = registry.get(artifactRelativePath);
GenericArtifactManager artifactManager;
if (resource.getMediaType().equals(soapServiceMediaType)){
artifactManager = new GenericArtifactManager(registry, "soapservice");
} else {
artifactManager = new GenericArtifactManager(registry, "service");
}
String artifactId = apiArtifact.getUUID();
artifact = artifactManager.getGenericArtifact(artifactId);
apiName = artifact.getAttribute("overview_name");
} catch (RegistryException e) {
LOG.error("Failed to convert service to xml content", e);
return false;
} catch (Exception e) {
LOG.error("Failed to convert service to xml content", e);
return false;
}
try {
publishDataToAPIM(resource, apiName);
} catch (GovernanceException e) {
LOG.error("Failed to convert service to xml content", e);
return false;
} catch (Exception e) {
LOG.error("Failed to convert service to xml content", e);
return false;
}
return true;
}
/**
* Update the APIM DB for the published API.
*
* @param resource
* @param serviceName
*/
private boolean publishDataToAPIM(Resource resource, String serviceName) throws GovernanceException {
boolean valid = true;
if (apimEndpoint == null || apimUsername == null || apimPassword == null || apimEnv == null) {
throw new GovernanceException(ExecutorConstants.APIM_LOGIN_UNDEFINED);
}
CookieStore cookieStore = new BasicCookieStore();
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
// APIUtils apiUtils = new APIUtils();
APIUtils.authenticateAPIM(httpContext, apimEndpoint, apimUsername, apimPassword);
String addAPIendpoint = apimEndpoint + Constants.APIM_ENDPOINT;
try {
// create a post request to addAPI.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(addAPIendpoint);
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>();
String[] endPoints=artifact.getAttributes(Constants.ENDPOINTS_ENTRY);
if (endPoints == null || endPoints.length == 0){
String msg = "Service Endpoint is a must attribute to create an API definition at the APIStore";
throw new GovernanceException(msg);
}
List<String> endPointsList= Arrays.asList(endPoints);
if (endPointsList==null){
String msg = "Service Endpoint is a must attribute to create an API definition at the APIStore";
throw new GovernanceException(msg);
}
addParameters(params, resource, serviceName);
LOG.info(new UrlEncodedFormEntity(params, Constants.UTF_8_ENCODE));
ResponseAPIM responseAPIM = APIUtils.callAPIMToPublishAPI(httpclient,httppost,params,httpContext);
if (responseAPIM.getError().equalsIgnoreCase(Constants.TRUE_CONSTANT)) {
LOG.error(responseAPIM.getMessage());
throw new GovernanceException("Error occurred while adding the api to API Manager.");
}
} catch (Exception e) {
throw new GovernanceException(e.getMessage(), e);
}
return valid;
}
private void addParameters(List<NameValuePair> params, Resource resource, String serviceName) throws GovernanceException{
String[] endPoints=artifact.getAttributes(Constants.ENDPOINTS_ENTRY);
List<String> endPointsList=Arrays.asList(endPoints);
//params.add(new BasicNameValuePair(API_ENDPOINT,getEnvironmentUrl(endPointsList)));
params.add(new BasicNameValuePair(API_ACTION, API_ADD_ACTION));
params.add(new BasicNameValuePair(API_NAME, serviceName));
params.add(new BasicNameValuePair(API_CONTEXT, serviceName));
params.add(new BasicNameValuePair(API_VERSION, artifact.getAttribute(SERVICE_VERSION)));
// params.add(new BasicNameValuePair(API_PROVIDER, resource.getProperty(Constants.OVERVIEW_BUSINESS_UNIT)));
params.add(new BasicNameValuePair(API_TIER, defaultTier));
params.add(new BasicNameValuePair(API_URI_PATTERN, DEFAULT_URI_PATTERN));
params.add(new BasicNameValuePair(API_URI_HTTP_METHOD, DEFAULT_HTTP_VERB));
params.add(new BasicNameValuePair(API_URI_AUTH_TYPE, DEFAULT_AUTH_TYPE));
params.add(new BasicNameValuePair(API_VISIBLITY, DEFAULT_VISIBILITY));
params.add(new BasicNameValuePair(API_THROTTLING_TIER, apiThrottlingTier));
params.add(new BasicNameValuePair(Constants.HTTP_CHECKED, Constants.HTTP_CONSTANT));
params.add(new BasicNameValuePair(Constants.HTTPS_CHECKED, Constants.HTTPS_CONSTANT));
params.add(new BasicNameValuePair(Constants.RESPONSE_CACHE, Constants.DISABLED));
params.add(new BasicNameValuePair(Constants.ENDPOINT_TYPE, Constants.NONSECURED));
params.add(new BasicNameValuePair(Constants.TAG, artifact.getAttribute(Constants.OVERVIEW_BUSINESS_UNIT)));
if (endPointsList.size() > 0) {
String endpointConfigJson = "{\"production_endpoints\":{\"url\":\"" +
getEnvironmentUrl(endPointsList) +
"\",\"config\":null},\"endpoint_type\":\"http\"}";
params.add(new BasicNameValuePair(Constants.ENDPOINT_CONFIG, endpointConfigJson));
}
params.add(new BasicNameValuePair(Constants.SUBSCRIPTIONS, Constants.CURRENT_TENANT));
}
private String getEnvironmentUrl(List<String> endpointsEntry) throws GovernanceException{
for (String att : endpointsEntry) {
if (att.substring(0, att.indexOf(Constants.COLUNM_SEPERATOR)).equalsIgnoreCase(apimEnv)) {
return att.substring(att.indexOf(Constants.COLUNM_SEPERATOR) + 1);
}
}
throw new GovernanceException("Related url is not available");
}
}