diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java index 28b846b96012..d9148d07cdc7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java @@ -316,8 +316,14 @@ List getSubscriptionsOfAPI(String apiName, String apiVersion, Str */ API updateAPI(API api, API existingAPI) throws APIManagementException, FaultGatewaysException; - void updateCustomBackend(API api,String type, InputStream sequence, String fileName) throws APIManagementException; - void updateCustomBackendByRevisionID(API api, String type, InputStream sequence, String revision, String fileName) throws APIManagementException; + void updateCustomBackend(API api,String type, InputStream sequence, String fileName, String customBackendUUID) throws APIManagementException; + Map getCustomBackendOfAPIByUUID(String customBackendUUID, String apiUUID, boolean isInfoOnly) throws APIManagementException; + + void updateCustomBackendByRevisionID(String apiUUID, String type, String revision, + String seqName, String backendUUID) throws APIManagementException; + + void addNewCustomBackendForRevision(String revisionUUID, String updatedBackendUUID, String apiUUID, + Map config) throws APIManagementException; /** * Create a new version of the api, with version newVersion diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/InMemoryAPIDeployer.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/InMemoryAPIDeployer.java index 8e3c5251426f..c37d7ef97d57 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/InMemoryAPIDeployer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/InMemoryAPIDeployer.java @@ -33,7 +33,6 @@ import org.apache.synapse.transport.dynamicconfigurations.DynamicProfileReloaderHolder; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.ExceptionCodes; -import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.gateway.GatewayAPIDTO; import org.wso2.carbon.apimgt.api.gateway.GatewayContentDTO; import org.wso2.carbon.apimgt.api.gateway.GraphQLSchemaDTO; @@ -350,7 +349,8 @@ private void unDeployAPI(APIGatewayAdmin apiGatewayAdmin, DeployAPIInGatewayEven } GatewayUtils.setCustomSequencesToBeRemoved(api, gatewayAPIDTO); - GatewayUtils.setCustomBackendToBeRemoved(api, gatewayAPIDTO); + // GatewayUtils.setCustomBackendToBeRemoved(api, gatewayAPIDTO); + } gatewayAPIDTO.setLocalEntriesToBeRemove( GatewayUtils diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 480bc33483b9..c23f10fb2dff 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -1543,8 +1543,6 @@ private OAuthConstants() { public static final String MEDIATION_SEQUENCE_ELEM = "sequence"; public static final String MEDIATION_CONFIG_EXT = ".xml"; public static final String API_CUSTOM_SEQ_IN_EXT = "--In"; - - public static final String API_CUSTOM_BACKEND_SEQ_EXT = "--Custom_Backend"; public static final String API_CUSTOM_SEQ_OUT_EXT = "--Out"; public static final String API_CUSTOM_SEQ_FAULT_EXT = "--Fault"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java index 87a5b36a93c5..1fea1b82b71c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java @@ -21,6 +21,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import jdk.internal.util.xml.impl.Input; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.util.AXIOMUtil; import org.apache.axis2.Constants; @@ -1041,15 +1044,29 @@ private void updateAPIPolicies(API api, String tenantDomain) throws APIManagemen } @Override - public void updateCustomBackend(API api, String type, InputStream sequence, String fileName) + public void updateCustomBackend(API api, String type, InputStream sequence, String seqName, String customBackendUUID) throws APIManagementException { - apiMgtDAO.updateCustomBackend(api.getUuid(), fileName, sequence, type); + apiMgtDAO.updateCustomBackend(api.getUuid(), seqName, sequence, type, customBackendUUID); } @Override - public void updateCustomBackendByRevisionID(API api, String type, InputStream sequence, - String revision, String fileName) throws APIManagementException { - apiMgtDAO.updateCustomBackendByRevision(api.getUuid(), fileName, sequence, type, revision); + public Map getCustomBackendOfAPIByUUID(String customBackendUUID, String apiUUID, boolean isInfoOnly) throws APIManagementException { + return apiMgtDAO.getCustomBackendOfAPIByUUID(customBackendUUID, apiUUID, isInfoOnly); + } + + @Override + public void updateCustomBackendByRevisionID(String apiUUID, String type, String revision, + String seqName, String backendUUID) throws APIManagementException { + String customBackendUUID = UUID.randomUUID().toString(); + InputStream sequence = apiMgtDAO.getCustomBackendSequenceOfAPIByUUID(backendUUID, apiUUID); + apiMgtDAO.updateCustomBackendByRevision(apiUUID, seqName, sequence, type, revision, customBackendUUID); + } + + @Override public void addNewCustomBackendForRevision(String revisionUUID, String updatedBackendUUID, String apiUUID, + Map config) throws APIManagementException { + InputStream sequence = apiMgtDAO.getCustomBackendSequenceOfAPIByUUID(updatedBackendUUID, apiUUID); + config.put("sequence", sequence); + apiMgtDAO.addNewCustomBackendForAPIRevision(apiUUID, revisionUUID, config); } private void validateKeyManagers(API api) throws APIManagementException { @@ -5242,6 +5259,7 @@ public API getAPIbyUUID(String uuid, String organization) throws APIManagementEx populateRevisionInformation(api, uuid); populateAPIInformation(uuid, organization, api); populateAPILevelPolicies(api); + if (APIUtil.isSequenceDefined(api.getInSequence()) || APIUtil.isSequenceDefined(api.getOutSequence()) || APIUtil.isSequenceDefined(api.getFaultSequence())) { if (migrationEnabled == null) { @@ -5287,6 +5305,23 @@ private void populateAPILevelPolicies(API api) throws APIManagementException { } } + private void populateCustomBackend(API api) throws APIManagementException { + JsonObject endpointConfig = JsonParser.parseString(api.getEndpointConfig()).getAsJsonObject(); + if(endpointConfig != null) { + if(endpointConfig.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE) != null && + APIConstants.ENDPOINT_TYPE_SEQUENCE.equals(endpointConfig.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE).getAsString())) { + ObjectMapper mapper = new ObjectMapper(); + // TODO: Check DB Queries. Following fetches data by API UUID and Revision ID = null + Map conf = apiMgtDAO.retrieveCustomBackendOfAPI(api.getUuid()); + try { + api.setEndpointConfig(mapper.writeValueAsString(conf)); + } catch (IOException ex) { + handleException("Error while converting endpointConfig to json", ex); + } + } + } + } + @Override public APISearchResult searchPaginatedAPIsByFQDN(String endpoint, String tenantDomain, int offset, int limit) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 0c895c540c2c..627ad6b9a2df 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -20,6 +20,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import jdk.internal.util.xml.impl.Input; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -2791,9 +2792,8 @@ public List getSubscriptionsOfAPI(String apiName, String apiVersi } /** - * @param apiName Name of the API - * @param apiVersion Version of the API - * @param provider Name of API creator + * @param apiUUID UUID of the API + * @param organization Organization of the API * @return All subscriptions of a given API * @throws org.wso2.carbon.apimgt.api.APIManagementException */ @@ -11194,6 +11194,66 @@ public Map retrieveCustomBackendOfAPIRevision(String apiUUID, St return map; } + public InputStream getCustomBackendSequenceOfAPIByUUID(String backendUUID, String apiUUID) throws APIManagementException { + String sqlQuery = SQLConstants.CustomBackendConstants.GET_API_SPECIFIC_CUSTOM_BACKEND_FROM_SEQUENCE_ID; + ResultSet rs = null; + InputStream sequence = null; + try (Connection con = APIMgtDBUtil.getConnection(); + PreparedStatement ps = con.prepareStatement(sqlQuery)) { + ps.setString(1, backendUUID); + ps.setString(2, apiUUID); + rs = ps.executeQuery(); + while(rs.next()) { + try (InputStream in = rs.getBinaryStream("SEQUENCE")) { + sequence = in; + } catch (IOException ex) { + handleException("Error reading the sequence of Custom Backend: "+ backendUUID + ", API: " + apiUUID, ex); + } + } + } catch (SQLException ex) { + handleException("Error when fetching Custom Backend data: "+ backendUUID + " of API: " + apiUUID, ex); + } + + if(sequence == null) { + throw new APIManagementException("Custom Backend Content cannot be empty"); + } + return sequence; + } + + public Map getCustomBackendOfAPIByUUID(String backendUUID, String apiUUID, boolean isInfo) throws APIManagementException { + String sqlQuery; + Map endpointConfig = new HashMap<>(); + boolean isRevisioned = checkAPIUUIDIsARevisionUUID(apiUUID) != null; + if(isRevisioned) { + sqlQuery = SQLConstants.CustomBackendConstants.GET_REVISION_SPECIFIC_CUSTOM_BACKEND_FROM_SEQUENCE_ID; + } else { + sqlQuery = SQLConstants.CustomBackendConstants.GET_API_SPECIFIC_CUSTOM_BACKEND_FROM_SEQUENCE_ID; + } + ResultSet resultSet = null; + try (Connection connection = APIMgtDBUtil.getConnection(); + PreparedStatement ps = connection.prepareStatement(sqlQuery)) { + ps.setString(1, backendUUID); + ps.setString(2, apiUUID); + resultSet = ps.executeQuery(); + while (resultSet.next()) { + if(!isInfo) { + try (InputStream in = resultSet.getBinaryStream("SEQUENCE")) { + endpointConfig.put("sequence", IOUtils.toString(in)); + } catch (IOException ex) { + handleException("Error reading Sequence Content of Custom Backend: " + backendUUID + " API: " + apiUUID, ex); + } + } + endpointConfig.put("type", resultSet.getString("TYPE")); + endpointConfig.put("sequence_name", resultSet.getString("NAME")); + endpointConfig.put("endpoint_type", "custom_backend"); + endpointConfig.put("sequence_id", resultSet.getString("ID")); + } + } catch (SQLException ex) { + handleException("Error when retrieving Custom Backend of API: " + apiUUID, ex); + } + return endpointConfig; + } + /** * * @param apiUUID API UUID @@ -11209,9 +11269,9 @@ public Map retrieveCustomBackendOfAPI(String apiUUID) throws API ps.setString(1, apiUUID); resultSet = ps.executeQuery(); while (resultSet.next()) { - map.put("sequence", resultSet.getString("SEQUENCE")); - map.put("endpoint_type", resultSet.getString("TYPE")); + map.put("type", resultSet.getString("TYPE")); map.put("sequence_name", resultSet.getString("NAME")); + map.put("endpoint_type", "custom_backend"); } } catch (SQLException ex) { handleException("Error retrieving Custom Backend of an API: " + apiUUID, ex); @@ -20794,14 +20854,15 @@ public void updateAPIPoliciesMapping(String apiUUID, Set uriTemplat } } - public void updateCustomBackend(String apiUUID, String sequenceName, InputStream sequence, String type) throws APIManagementException { + public void updateCustomBackend(String apiUUID, String sequenceName, InputStream sequence, String type, String backendUUID) throws APIManagementException { String deleteCustomBackedQuery = SQLConstants.CustomBackendConstants.DELETE_CUSTOM_BACKEND; try (Connection connection = APIMgtDBUtil.getConnection(); PreparedStatement prepStmt = connection.prepareStatement(deleteCustomBackedQuery)) { connection.setAutoCommit(false); prepStmt.setString(1, apiUUID); + prepStmt.setString(2, backendUUID); prepStmt.executeUpdate(); - addCustomBackend(apiUUID, sequenceName, null, sequence, type, connection); + addCustomBackend(apiUUID, sequenceName, null, sequence, type, connection, backendUUID); connection.commit(); } catch (SQLException e) { handleException("Error while adding Custom Backend for API : " + apiUUID, e); @@ -20822,7 +20883,8 @@ public void deleteCustomBackend(String apiUUID, String revisionId) throws APIMan } } - public void updateCustomBackendByRevision(String apiUUID, String sequenceName, InputStream sequence, String type, String revision) throws APIManagementException { + public void updateCustomBackendByRevision(String apiUUID, String sequenceName, InputStream sequence, String type, + String revision, String backendUUID) throws APIManagementException { String deleteCustomBackedQuery = SQLConstants.CustomBackendConstants.DELETE_CUSTOM_BACKEND_BY_REVISION; try (Connection connection = APIMgtDBUtil.getConnection(); PreparedStatement prepStmt = connection.prepareStatement(deleteCustomBackedQuery)) { @@ -20830,22 +20892,45 @@ public void updateCustomBackendByRevision(String apiUUID, String sequenceName, I prepStmt.setString(1, apiUUID); prepStmt.setString(2, revision); prepStmt.executeUpdate(); - addCustomBackend(apiUUID, sequenceName, revision, sequence, type, connection); + addCustomBackend(apiUUID, sequenceName, revision, sequence, type, connection, backendUUID); connection.commit(); } catch (SQLException e) { handleException("Error while adding Custom Backend for API : " + apiUUID, e); } } - public void addCustomBackend(String apiUUID, String sequenceName, String revision, InputStream sequence, String type, Connection connection) throws APIManagementException { + public void addNewCustomBackendForAPIRevision(String apiUUID, String revisionID, Map endpointConfig) throws APIManagementException { + String addSqlQuery = SQLConstants.CustomBackendConstants.ADD_CUSTOM_BACKEND; + try (Connection con = APIMgtDBUtil.getConnection(); + PreparedStatement ps = con.prepareStatement(addSqlQuery)) { + String backendUUID = endpointConfig.get("sequence_id").toString(); + InputStream sequence = (InputStream) endpointConfig.get("sequence"); + String type = endpointConfig.get("type").toString(); + String sequenceName = endpointConfig.get("sequence_name").toString(); + con.setAutoCommit(false); + ps.setString(1, backendUUID); + ps.setString(2, apiUUID); + ps.setBinaryStream(3, sequence); + ps.setString(4, type); + ps.setString(5, revisionID); + ps.setString(6, sequenceName); + ps.executeUpdate(); + } catch (SQLException ex) { + handleException("Error when inserting Custom Backend data for API: " + apiUUID, ex); + } + } + + public void addCustomBackend(String apiUUID, String sequenceName, String revision, InputStream sequence, + String type, Connection connection, String backendUUID) throws APIManagementException { String insertCustomBackendQuery = SQLConstants.CustomBackendConstants.ADD_CUSTOM_BACKEND; try (PreparedStatement prepStmt = connection.prepareStatement(insertCustomBackendQuery)) { connection.setAutoCommit(false); - prepStmt.setString(1, apiUUID); - prepStmt.setBinaryStream(2, sequence); - prepStmt.setString(3, type); - prepStmt.setString(4, revision); - prepStmt.setString(5, sequenceName); + prepStmt.setString(1, backendUUID); + prepStmt.setString(2, apiUUID); + prepStmt.setBinaryStream(3, sequence); + prepStmt.setString(4, type); + prepStmt.setString(5, revision); + prepStmt.setString(6, sequenceName); prepStmt.executeUpdate(); } catch (SQLException e) { handleException("Error while adding Custom Backend for API : " + apiUUID, e); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index dbd85563fc74..0277df9a6526 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -4403,12 +4403,18 @@ public static class SystemConfigsConstants { public static class CustomBackendConstants { public static final String ADD_CUSTOM_BACKEND = - "INSERT INTO AM_API_CUSTOM_BACKEND (API_UUID,SEQUENCE,TYPE,REVISION_UUID,NAME) " + "VALUES (?,?,?,?,?)"; - public static final String DELETE_CUSTOM_BACKEND = "DELETE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND REVISION_UUID IS NULL"; + "INSERT INTO AM_API_CUSTOM_BACKEND (ID,API_UUID,SEQUENCE,TYPE,REVISION_UUID,NAME) " + "VALUES (?,?,?,?,?,?)"; + public static final String DELETE_CUSTOM_BACKEND = "DELETE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND ID = ? AND REVISION_UUID IS NULL"; public static final String DELETE_CUSTOM_BACKEND_BY_REVISION = "DELETE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND REVISION_UUID = ?"; public static final String DELETE_CUSTOM_BACKEND_BY_API = "DELETE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ?"; public static final String GET_CUSTOM_BACKEND_OF_API_REVISION = "SELECT NAME, SEQUENCE, TYPE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND REVISION_UUID = ?"; - public static final String GET_CUSTOM_BACKEND_OF_API_DEFAULT_REVISION = "SELECT NAME, SEQUENCE, TYPE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND REVISION_UUID IS NULL"; + public static final String GET_CUSTOM_BACKEND_OF_API_DEFAULT_REVISION = "SELECT ACB.NAME, ACB.TYPE FROM AM_API_CUSTOM_BACKEND WHERE API_UUID = ? AND REVISION_UUID IS NULL"; + public static final String GET_REVISION_SPECIFIC_CUSTOM_BACKEND_FROM_SEQUENCE_ID = "SELECT ACB.ID, ACB.NAME, ACB.SEQUENCE, ACB.TYPE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND ACB.REVISION_UUID = ?"; + public static final String GET_API_SPECIFIC_CUSTOM_BACKEND_FROM_SEQUENCE_ID = "SELECT ACB.ID, ACB.NAME, ACB.SEQUENCE, ACB.TYPE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND API_UUID = ? AND REVISION_UUID IS NULL"; + public static final String GET_REVISION_SPECIFIC_CUSTOM_BACKEND_META_DATA_FROM_SEQUENCE_ID = "SELECT ACB.ID, ACB.NAME, ACB.TYPE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND ACB.REVISION_UUID = ?"; + public static final String GET_API_SPECIFIC_CUSTOM_BACKEND_META_DATA_FROM_SEQUENCE_ID = "SELECT ACB.ID, ACB.NAME, ACB.TYPE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND API_UUID = ?"; + public static final String GET_API_SPECIFIC_CUSTOM_BACKEND_SEQUENCE_FROM_SEQUENCE_ID = "SELECT ACB.SEQUENCE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND API_UUID = ?"; + public static final String GET_REVISION_SPECIFIC_CUSTOM_BACKEND_SEQUENCE_FROM_SEQUENCE_ID = "SELECT ACB.SEQUENCE FROM AM_API_CUSTOM_BACKEND ACB WHERE ACB.ID = ? AND ACB.REVISION_UUID = ?"; } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/importexport/ImportExportConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/importexport/ImportExportConstants.java index 0beb53f2baa5..267a6b8feb95 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/importexport/ImportExportConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/importexport/ImportExportConstants.java @@ -309,6 +309,7 @@ public final class ImportExportConstants { public static final String DISPLAY_ON_DEVPORTAL_OPTION = "displayOnDevportal"; public static final String POLICIES_DIRECTORY = "Policies"; + public static final String CUSTOM_BACKEND_DIRECTORY = "Custom-Backend"; public static final String SWAGGER_X_WSO2_APICTL_INIT = "x-wso2-apictl-init"; public static final String EXPORT_POLICY_TYPE_YAML = "YAML"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index fe11c1e38214..56639d21549a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -4290,6 +4290,10 @@ public static String getSequenceExtensionName(API api) { return api.getId().getApiName() + ":v" + api.getId().getVersion(); } + public static String getCustomBackendName(String apiUUID, String type) { + return apiUUID + "-" + type; + } + /** * Return the sequence extension name. * eg: admin--testAPi--v1.00 @@ -10009,6 +10013,27 @@ public static OperationPolicyDefinition getOperationPolicyDefinitionFromFile(Str return policyDefinition; } + public static String getOperationCustomBackendSequenceFromFile(String extractedFolderPath, + String sequenceName, + String fileExtension) + throws APIManagementException { + + String customBackendContent = null; + try { + String fileName = extractedFolderPath + File.separator + sequenceName + fileExtension; + if (checkFileExistence(fileName)) { + if (log.isDebugEnabled()) { + log.debug("Found policy definition file " + fileName); + } + customBackendContent = FileUtils.readFileToString(new File(fileName)); + } + } catch (IOException e) { + throw new APIManagementException("Error while reading Custom Backend from path: " + + extractedFolderPath, e, ExceptionCodes.ERROR_READING_META_DATA); + } + return customBackendContent; + } + /** * Check whether there exists a file for the provided location * @@ -10208,6 +10233,10 @@ public static String getOperationPolicyFileName(String policyName, String policy return policyName + "_" + policyVersion; } + public static String getCustomBackendFileName(String apiUUID, String endpointType) { + return apiUUID + "-" + endpointType; + } + public static void initializeVelocityContext(VelocityEngine velocityEngine){ velocityEngine.setProperty(RuntimeConstants.OLD_CHECK_EMPTY_OBJECTS, false); velocityEngine.setProperty(DeprecatedRuntimeConstants.OLD_SPACE_GOBBLING,"bc"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/GatewayUtils.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/GatewayUtils.java index f82916f353aa..633844789fc2 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/GatewayUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/GatewayUtils.java @@ -46,11 +46,6 @@ public static void setCustomSequencesToBeRemoved(API api, GatewayAPIDTO gatewayA gatewayAPIDTO.setSequencesToBeRemove(addStringToList(faultSequence, gatewayAPIDTO.getSequencesToBeRemove())); } - public static void setCustomBackendToBeRemoved(API api, GatewayAPIDTO gatewayAPIDTO) { - String sequence = APIUtil.getSequenceExtensionName(api) + APIConstants.API_CUSTOM_SEQ_IN_EXT + APIConstants.API_CUSTOM_BACKEND_SEQ_EXT; - gatewayAPIDTO.setSequencesToBeRemove(addStringToList(sequence, gatewayAPIDTO.getSequencesToBeRemove())); - } - public static String[] addStringToList(String key, String[] keys) { if (keys == null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index 1a5cf18b269e..22c32227ea48 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -487,6 +487,95 @@ paths: -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/topics"' + /apis/{apiId}/custom-backend/{customBackendId}: + get: + tags: + - APIs + summary: Get Custom Backend of the API + description: This operation can be used to get Custom Backend data of the API + operationId: getCustomBackendData + parameters: + - $ref: '#/components/parameters/customBackendId' + - $ref: '#/components/parameters/apiId' + responses: + 200: + description: | + OK. + Requested API Custom Backend is returned + headers: + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + schema: + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + schema: + type: string + Content-Type: + description: | + The content type of the body. + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/CustomBackend' + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + content: {} + 404: + $ref: '#/components/responses/NotFound' + 406: + $ref: '#/components/responses/NotAcceptable' + security: + - OAuth2Security: + - apim:api_view + - apim:api_manage + - apim:api_import_export + - apim:api_product_import_export + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/custom-backend/7a2298c4-c915-483f-8fac-38c73301631f"' + delete: + tags: + - APIs + summary: Delete Custom Backend of the API + description: This operation can be used to remove the Custom Backend of the API + operationId: customBackendDelete + parameters: + - $ref: '#/components/parameters/apiId' + - $ref: '#/components/parameters/If-Match' + - $ref: '#/components/parameters/customBackendId' + responses: + 200: + description: | + OK. + Resource successfully deleted. + content: { } + 403: + $ref: '#/components/responses/Forbidden' + 404: + $ref: '#/components/responses/NotFound' + 409: + $ref: '#/components/responses/Conflict' + 412: + $ref: '#/components/responses/PreconditionFailed' + security: + - OAuth2Security: + - apim:api_delete + - apim:api_manage + - apim:api_import_export + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/custom-backend/7a2298c4-c915-483f-8fac-38c73301631f"' + /apis/{apiId}/custom-backend: put: tags: @@ -9279,6 +9368,26 @@ paths: -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/workflows/update-workflow-status?workflowReferenceId=56e3a170-a7a7-45f8-b051-7e43a58a67e1"' components: schemas: + CustomBackend: + title: Custom Backend + type: object + properties: + sequenceId: + type: string + readOnly: true + example: 943d3002-000c-42d3-a1b9-d6559f8a4d49 + sequenceName: + type: string + readOnly: true + example: 943d3002-000c-42d3-a1b9-d6559f8a4d49-SANDBOX + sequenceType: + type: string + readOnly: true + example: SANDBOX + sequence: + type: string + format: binary + readOnly: true Comment: title: Comment required: @@ -13381,6 +13490,14 @@ components: schema: type: integer default: 0 + customBackendId: + name: customBackendId + in: path + description: | + Custom Backend ID + required: true + schema: + type: string commentId: name: commentId in: path diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapseArtifactGenerator.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapseArtifactGenerator.java index 54615455d838..abe5153019e0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapseArtifactGenerator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapseArtifactGenerator.java @@ -115,7 +115,7 @@ public RuntimeArtifactDto generateGatewayArtifact(List ap } else { APIDTO apidto = ImportUtils.retrievedAPIDto(extractedFolderPath); // Update the EndpointConfig if it's a Custom Backend - updateCustomBackendOfAPI(apidto, runTimeArtifact.getRevision()); + // updateCustomBackendOfAPI(apidto, runTimeArtifact.getRevision()); API api = APIMappingUtil.fromDTOtoAPI(apidto, apidto.getProvider()); api.setUUID(apidto.getId()); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapsePolicyAggregator.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapsePolicyAggregator.java index 0bdc79ec7534..ae350198d250 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapsePolicyAggregator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/SynapsePolicyAggregator.java @@ -107,26 +107,18 @@ public static String generatePolicySequenceForUriTemplateSet(Set ur } } - public static String generateBackendSequenceForCustomSequence(API api, String sequenceName, String flow, - String sequence, String endpointType) throws APIManagementException, IOException { + public static String generateBackendSequenceForCustomSequence(String sequenceName, String pathToArchive, String endpointType) throws APIManagementException, IOException { Map configMap = new HashMap<>(); - boolean render = false; String customBackendTemplate = FileUtil.readFileToString(CUSTOM_BACKEND_SEQUENCE_TEMPLATE_LOCATION) .replace("\\", ""); configMap.put("sequence_name", sequenceName); - if (sequence != null || sequence.isEmpty()) { - String sanitizedSequence = renderCustomBackendSequence(sequence, sequenceName); - if (sanitizedSequence == null) { - throw new APIManagementException("Error when preparing the sequence: " + sequenceName); - } - configMap.put("custom_sequence", sanitizedSequence); - configMap.put("endpoint_type", endpointType); - render = true; + String sanitizedSequence = renderCustomBackendSequence(sequenceName, pathToArchive); + if (sanitizedSequence == null) { + throw new APIManagementException("Error when preparing the sequence: " + sequenceName); } - if (render) { - return renderPolicyTemplate(customBackendTemplate, configMap); - } - return ""; + configMap.put("custom_sequence", sanitizedSequence); + configMap.put("endpoint_type", endpointType); + return renderPolicyTemplate(customBackendTemplate, configMap); } /** @@ -227,11 +219,10 @@ private static List renderPolicyMapping(List policyList return renderedPolicyMappingList; } - private static String renderCustomBackendSequence(String sequence, String sequenceName) { - if (sequence != null) { - return renderPolicyTemplate(sequence, new HashMap<>()); - } - return null; + private static String renderCustomBackendSequence(String sequenceName, String pathToArchive) throws APIManagementException { + String policyDirectory = pathToArchive + File.separator + ImportExportConstants.CUSTOM_BACKEND_DIRECTORY; + String sequence = APIUtil.getOperationCustomBackendSequenceFromFile(policyDirectory, sequenceName, ".xml"); + return renderPolicyTemplate(sequence, new HashMap<>()); } /** diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/TemplateBuilderUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/TemplateBuilderUtil.java index 8279b4ab67c8..8dc6f7578938 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/TemplateBuilderUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/TemplateBuilderUtil.java @@ -923,11 +923,9 @@ private static void setCustomSequencesToBeAdded(API api, GatewayAPIDTO gatewayAP Map endpointConfigMap = (Map) apidto.getEndpointConfig(); if (APIConstants.ENDPOINT_TYPE_SEQUENCE.equals( - endpointConfigMap.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE)) - && endpointConfigMap.get("sequence") != null) { + endpointConfigMap.get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE))) { GatewayContentDTO gatewayCustomBackendSequenceDTO = retrieveCustomBackendSequence(api, - APIConstants.OPERATION_SEQUENCE_TYPE_REQUEST, endpointConfigMap.get("sequence").toString(), - endpointConfigMap.get("type").toString()); + endpointConfigMap.get("type").toString(), extractedPath); if (gatewayCustomBackendSequenceDTO != null) { gatewayAPIDTO.setSequenceToBeAdd( addGatewayContentToList(gatewayCustomBackendSequenceDTO, gatewayAPIDTO.getSequenceToBeAdd())); @@ -1380,16 +1378,15 @@ private static GatewayContentDTO retrieveOperationPolicySequence(String pathToAc return null; } - private static GatewayContentDTO retrieveCustomBackendSequence(API api, String flow, String sequence, - String endpointType) throws APIManagementException { + private static GatewayContentDTO retrieveCustomBackendSequence(API api, String endpointType, String pathToAchieve) + throws APIManagementException { GatewayContentDTO customBackendSequenceContentDto = new GatewayContentDTO(); String customSequence = null; - String seqExt = APIUtil.getSequenceExtensionName(api) + SynapsePolicyAggregator.getSequenceExtensionFlow(flow) - + "-Custom-Backend"; + String seqExt = APIUtil.getCustomBackendName(api.getUuid(), endpointType); try { - customSequence = SynapsePolicyAggregator.generateBackendSequenceForCustomSequence(api, seqExt, flow, - sequence, endpointType); + customSequence = SynapsePolicyAggregator.generateBackendSequenceForCustomSequence(seqExt, + pathToAchieve, endpointType); } catch (IOException e) { throw new APIManagementException(e); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java index f5cad2b8e810..5916c3b8c990 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java @@ -206,15 +206,6 @@ public static API fromDTOtoAPI(APIDTO dto, String provider) throws APIManagement if (endpointConfig instanceof LinkedHashMap) { ((LinkedHashMap) endpointConfig).remove(APIConstants.IMPLEMENTATION_STATUS); } - if (endpointConfig instanceof HashMap) { - if (APIConstants.ENDPOINT_TYPE_SEQUENCE.equals( - ((HashMap) endpointConfig).get(APIConstants.API_ENDPOINT_CONFIG_PROTOCOL_TYPE))) { - String seqExt = APIUtil.getSequenceExtensionName(dto.getName(), dto.getVersion()) - + SynapsePolicyAggregator.getSequenceExtensionFlow( - APIConstants.OPERATION_SEQUENCE_TYPE_REQUEST) + "-Custom-Backend"; - ((HashMap) endpointConfig).put("sequence_name", seqExt); - } - } model.setEndpointConfig(mapper.writeValueAsString(endpointConfig)); } catch (IOException e) { handleException("Error while converting endpointConfig to json", e); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ExportUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ExportUtils.java index c318151d3d2e..71c9edced5cf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ExportUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ExportUtils.java @@ -86,6 +86,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import static org.wso2.carbon.apimgt.impl.APIConstants.API_DATA_PRODUCTION_ENDPOINTS; @@ -216,6 +217,13 @@ public static File exportApi(APIProvider apiProvider, APIIdentifier apiIdentifie String tenantDomain = APIUtil.getTenantDomainFromTenantId(tenantId); addOperationPoliciesToArchive(archivePath, tenantDomain, exportFormat, apiProvider, api, currentApiUuid); + + // TODO: Add Custom Backend to the Archive + JsonObject endpointConfig = JsonParser.parseString(api.getEndpointConfig()).getAsJsonObject(); + if(APIConstants.ENDPOINT_TYPE_SEQUENCE.equals(endpointConfig.get(API_ENDPOINT_CONFIG_PROTOCOL_TYPE).getAsString())) { + addCustomBackendToAPI(archivePath, apiProvider, api, currentApiUuid, endpointConfig); + } + addGatewayEnvironmentsToArchive(archivePath, apiDtoToReturn.getId(), exportFormat, apiProvider); if (migrationEnabled != null) { @@ -628,6 +636,23 @@ public static void addEndpointCertificatesToArchive(String archivePath, APIDTO a } } + public static void addCustomBackendToAPI(String archivePath, + APIProvider apiProvider, API api, String currentApiUuid, JsonObject endpointConfig) throws APIManagementException { + String exportedCustomBackend = null; + try { + String backendUUID = endpointConfig.get("sequence_id").getAsString(); + CommonUtil.createDirectory(archivePath + File.separator + ImportExportConstants.CUSTOM_BACKEND_DIRECTORY); + String customBackendName = APIUtil.getCustomBackendName(api.getUuid(), endpointConfig.get("type").getAsString()); + Map endpointConfigMap = apiProvider.getCustomBackendOfAPIByUUID(backendUUID, currentApiUuid, false); + if(endpointConfigMap != null) { + exportCustomBackend(customBackendName, endpointConfigMap, archivePath); + } + + } catch (IOException | APIImportExportException ex) { + + } + } + /** * Retrieve the operation policies and store those in the archive directory. * @@ -736,6 +761,14 @@ public static void exportPolicyData(String policyFileName, OperationPolicyData p } } + public static void exportCustomBackend(String customBackendFileName, Map endpointConfig, String archivePath) throws APIImportExportException, IOException { + String customBackendName = archivePath + File.separator + ImportExportConstants.CUSTOM_BACKEND_DIRECTORY + File.separator + customBackendFileName; + if(endpointConfig != null && endpointConfig.get(API_ENDPOINT_CONFIG_PROTOCOL_TYPE) != null && APIConstants.ENDPOINT_TYPE_SEQUENCE.equals(endpointConfig.get( + API_ENDPOINT_CONFIG_PROTOCOL_TYPE))) { + CommonUtil.writeFile(customBackendName + APIConstants.SYNAPSE_POLICY_DEFINITION_EXTENSION_XML, endpointConfig.get("sequence")); + } + } + /** * Retrieve the deployed gateway environments and store those in the archive directory. * diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index 498b1c8c01ad..61cb45405e82 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -108,6 +108,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -201,14 +202,22 @@ public static API updateApi(API originalAPI, APIDTO apiDtoToUpdate, APIProvider * @return Custom Backend File Name * @throws APIManagementException If an error occurs while updating the API and API definition */ - public static String updateCustomBackend(API api, APIProvider apiProvider, String endpointType, + public static JSONObject updateCustomBackend(API api, APIProvider apiProvider, String endpointType, InputStream customBackend, String contentDecomp) throws APIManagementException { String fileName = getFileNameFromContentDisposition(contentDecomp); if (fileName == null) throw new APIManagementException( "Error when retrieving Custom Backend file name of API: " + api.getId().getApiName()); - apiProvider.updateCustomBackend(api, endpointType, customBackend, fileName); - return fileName; + String seqName = APIUtil.getCustomBackendName(api.getUuid(), endpointType); + String customBackendUUID = UUID.randomUUID().toString(); + apiProvider.updateCustomBackend(api, endpointType, customBackend, seqName, customBackendUUID); + JSONObject obj = new JSONObject(); + obj.put("sequence_name", seqName); + obj.put("sequence_file", fileName); + obj.put("sequence_id", customBackendUUID); + obj.put("type", endpointType); + obj.put("endpoint_type", "custom_backend"); + return obj; } private static String getFileNameFromContentDisposition(String contentDisposition) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java index 15f8405eb71a..dc9c9655ee1d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java @@ -21,10 +21,6 @@ import com.amazonaws.SdkClientException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.internal.LinkedTreeMap; import org.apache.commons.collections.MapUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; @@ -212,11 +208,9 @@ public Response getAPI(String apiId, String xWSO2Tenant, String ifNoneMatch, MultivaluedMap headers = sequenceDetail.getHeaders(); String contentDecomp = headers.getFirst("Content-Disposition"); - String sequenceName = PublisherCommonUtils.updateCustomBackend(api, apiProvider, type, sequenceInputStream, + JSONObject resp = PublisherCommonUtils.updateCustomBackend(api, apiProvider, type, sequenceInputStream, contentDecomp); - JSONObject obj = new JSONObject(); - obj.put("sequenceName", sequenceName); - return Response.ok().entity(obj).build(); + return Response.ok().entity(resp).build(); } @Override @@ -3770,6 +3764,20 @@ public Response createAPIRevision(String apiId, APIRevisionDTO apIRevisionDTO, M //adding the api revision String revisionId = apiProvider.addAPIRevision(apiRevision, organization); + Object endpointConfig = apiDto.getEndpointConfig(); + + if (endpointConfig != null && endpointConfig instanceof HashMap) { + String endpointType = ((HashMap) endpointConfig).get("endpoint_type").toString(); + if (endpointType != null && APIConstants.ENDPOINT_TYPE_SEQUENCE.equals(endpointType)) { + String sequenceName = ((HashMap) endpointConfig).get("sequence_name").toString(); + String sequenceEndpointType = ((HashMap) endpointConfig).get("sequence_type").toString(); + String backendUUID = ((HashMap) endpointConfig).get("sequence_id").toString(); + // Update Custom Backend table + apiProvider.addNewCustomBackendForRevision(revisionId, backendUUID, apiId, + (HashMap) endpointConfig); + } + } + //Retrieve the newly added APIRevision to send in the response payload APIRevision createdApiRevision = apiProvider.getAPIRevision(revisionId); APIRevisionDTO createdApiRevisionDTO = APIMappingUtil.fromAPIRevisiontoDTO(createdApiRevision); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index 1a5cf18b269e..d22fd1138b3a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -487,6 +487,96 @@ paths: -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/topics"' + + /apis/{apiId}/custom-backend/{customBackendId}: + get: + tags: + - APIs + summary: Get Custom Backend of the API + description: This operation can be used to get Custom Backend data of the API + operationId: getCustomBackendData + parameters: + - $ref: '#/components/parameters/customBackendId' + - $ref: '#/components/parameters/apiId' + responses: + 200: + description: | + OK. + Requested API Custom Backend is returned + headers: + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + schema: + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + schema: + type: string + Content-Type: + description: | + The content type of the body. + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/CustomBackend' + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + content: {} + 404: + $ref: '#/components/responses/NotFound' + 406: + $ref: '#/components/responses/NotAcceptable' + security: + - OAuth2Security: + - apim:api_view + - apim:api_manage + - apim:api_import_export + - apim:api_product_import_export + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/custom-backend/7a2298c4-c915-483f-8fac-38c73301631f"' + delete: + tags: + - APIs + summary: Delete Custom Backend of the API + description: This operation can be used to remove the Custom Backend of the API + operationId: customBackendDelete + parameters: + - $ref: '#/components/parameters/apiId' + - $ref: '#/components/parameters/If-Match' + - $ref: '#/components/parameters/customBackendId' + responses: + 200: + description: | + OK. + Resource successfully deleted. + content: { } + 403: + $ref: '#/components/responses/Forbidden' + 404: + $ref: '#/components/responses/NotFound' + 409: + $ref: '#/components/responses/Conflict' + 412: + $ref: '#/components/responses/PreconditionFailed' + security: + - OAuth2Security: + - apim:api_delete + - apim:api_manage + - apim:api_import_export + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/apis/7a2298c4-c905-403f-8fac-38c73301631f/custom-backend/7a2298c4-c915-483f-8fac-38c73301631f"' + /apis/{apiId}/custom-backend: put: tags: @@ -9279,6 +9369,26 @@ paths: -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/workflows/update-workflow-status?workflowReferenceId=56e3a170-a7a7-45f8-b051-7e43a58a67e1"' components: schemas: + CustomBackend: + title: Custom Backend + type: object + properties: + sequenceId: + type: string + readOnly: true + example: 943d3002-000c-42d3-a1b9-d6559f8a4d49 + sequenceName: + type: string + readOnly: true + example: 943d3002-000c-42d3-a1b9-d6559f8a4d49-SANDBOX + sequenceType: + type: string + readOnly: true + example: SANDBOX + sequence: + type: string + format: binary + readOnly: true Comment: title: Comment required: @@ -13381,6 +13491,14 @@ components: schema: type: integer default: 0 + customBackendId: + name: customBackendId + in: path + description: | + Custom Backend ID + required: true + schema: + type: string commentId: name: commentId in: path diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql index a4bace7ddf78..11dff57f1f47 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql @@ -1521,6 +1521,17 @@ CREATE TABLE IF NOT EXISTS AM_API ( UNIQUE (API_UUID) )ENGINE INNODB; +CREATE TABLE IF NOT EXISTS AM_API_CUSTOM_BACKEND ( + ID VARCHAR(60) NOT NULL, + API_UUID VARCHAR(256) NOT NULL, + REVISION_UUID VARCHAR(256), + SEQUENCE LONGBLOB, + NAME VARCHAR(256) NOT NULL, + TYPE VARCHAR(120) NOT NULL, + PRIMARY KEY (ID, API_UUID, REVISION_UUID), + FOREIGN KEY (API_UUID) REFERENCES AM_API(API_UUID) ON DELETE CASCADE +)ENGINE INNODB; + CREATE TABLE IF NOT EXISTS AM_GRAPHQL_COMPLEXITY ( UUID VARCHAR(256), API_ID INTEGER NOT NULL,