diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml
new file mode 100644
index 00000000000..2dca4947dba
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+ apimgt-extensions
+ org.wso2.carbon.devicemgt
+ 5.0.26-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ io.entgra.device.mgt.core.apimgt.extension.rest.api
+ bundle
+ Entgra - Device Management Extension for APIM REST API
+ Entgra - Device Management Extension for APIM REST API
+ https://entgra.io
+
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+ provided
+
+
+ org.wso2.carbon
+ org.wso2.carbon.utils
+ provided
+
+
+ org.wso2.carbon
+ org.wso2.carbon.core
+ provided
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi
+ provided
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi.services
+ provided
+
+
+
+ org.json.wso2
+ json
+
+
+ com.google.code.gson
+ gson
+ provided
+
+
+ org.wso2.carbon.apimgt
+ org.wso2.carbon.apimgt.impl
+ provided
+
+
+ com.squareup.okhttp3
+ okhttp
+ compile
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ 5.1.7
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+ ${carbon.device.mgt.version}
+ Publisher API Management Bundle
+
+ io.entgra.device.mgt.core.apimgt.extension.rest.api.internal
+
+
+ !io.entgra.device.mgt.core.apimgt.extension.rest.api.internal,
+ io.entgra.device.mgt.core.apimgt.extension.rest.api.*
+
+
+ org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
+ org.osgi.service.*;version="${imp.package.version.osgi.service}",
+ org.wso2.carbon.core;version="4.6",
+ org.wso2.carbon.core.util;version="4.6",
+ org.apache.commons.ssl,
+ org.wso2.carbon.apimgt.api.model,
+ okhttp3.*,
+ org.wso2.carbon.apimgt.impl;version="${carbon.api.mgt.version.range}",
+ org.wso2.carbon.apimgt.impl.utils;version="${carbon.api.mgt.version.range}",
+ org.wso2.carbon.apimgt.impl.internal;version="${carbon.api.mgt.version.range}",
+ org.json
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+
+
+
+ jacoco-initialize
+
+ prepare-agent
+
+
+
+ jacoco-site
+ test
+
+ report
+
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+ ${basedir}/target/coverage-reports/site
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServices.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServices.java
new file mode 100644
index 00000000000..51d7d20b17f
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServices.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api;
+
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
+
+public interface APIApplicationServices {
+
+ APIApplicationKey createAndRetrieveApplicationCredentials() throws APIServicesException;
+
+ AccessTokenInfo generateAccessTokenFromRegisteredApplication(String clientId, String clientSecret) throws APIServicesException;
+
+ AccessTokenInfo generateAccessTokenFromRefreshToken(String refreshToken, String clientId, String clientSecret) throws APIServicesException;
+
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServicesImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServicesImpl.java
new file mode 100644
index 00000000000..68faf24b80a
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/APIApplicationServicesImpl.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api;
+
+import com.google.gson.Gson;
+import org.json.JSONObject;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.RequestBody;
+import okhttp3.Credentials;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
+import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
+import java.io.IOException;
+
+public class APIApplicationServicesImpl implements APIApplicationServices {
+
+ private static final Log log = LogFactory.getLog(APIApplicationServicesImpl.class);
+ private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
+ private static final Gson gson = new Gson();
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ String msg = null;
+ APIManagerConfiguration config = ServiceReferenceHolder.getInstance().
+ getAPIManagerConfigurationService().getAPIManagerConfiguration();
+
+ @Override
+ public APIApplicationKey createAndRetrieveApplicationCredentials()
+ throws APIServicesException {
+
+ String applicationEndpoint = config.getFirstProperty(Constants.DCR_END_POINT);
+ String serverUser = config.getFirstProperty(Constants.SERVER_USER);
+ String serverPassword = config.getFirstProperty(Constants.SERVER_PASSWORD);
+
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("callbackUrl", Constants.EMPTY_STRING);
+ jsonObject.put("clientName", Constants.CLIENT_NAME);
+ jsonObject.put("grantType", Constants.GRANT_TYPE);
+ jsonObject.put("owner", serverUser);
+ jsonObject.put("saasApp", true);
+
+ RequestBody requestBody = RequestBody.Companion.create(jsonObject.toString(), JSON);
+ Request request = new Request.Builder()
+ .url(applicationEndpoint)
+ .addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(serverUser, serverPassword))
+ .post(requestBody)
+ .build();
+ try {
+ Response response = client.newCall(request).execute();
+ return gson.fromJson(response.body().string(), APIApplicationKey.class);
+ } catch (IOException e) {
+ msg = "Error occurred while processing the response";
+ log.error(msg, e);
+ throw new APIServicesException(e);
+ }
+ }
+
+ @Override
+ public AccessTokenInfo generateAccessTokenFromRegisteredApplication(String consumerKey, String consumerSecret)
+ throws APIServicesException {
+
+ String userName = config.getFirstProperty(Constants.SERVER_USER);
+ String userPassword = config.getFirstProperty(Constants.SERVER_PASSWORD);
+
+ JSONObject params = new JSONObject();
+ params.put(Constants.GRANT_TYPE_PARAM_NAME, Constants.PASSWORD_GRANT_TYPE);
+ params.put(Constants.PASSWORD_GRANT_TYPE_USERNAME, userName);
+ params.put(Constants.PASSWORD_GRANT_TYPE_PASSWORD, userPassword);
+ params.put(Constants.SCOPE_PARAM_NAME, Constants.SCOPES);
+ return getToken(params, consumerKey, consumerSecret);
+ }
+
+ @Override
+ public AccessTokenInfo generateAccessTokenFromRefreshToken(String refreshToken, String consumerKey, String consumerSecret)
+ throws APIServicesException {
+
+ JSONObject params = new JSONObject();
+ params.put(Constants.GRANT_TYPE_PARAM_NAME, Constants.REFRESH_TOKEN_GRANT_TYPE);
+ params.put(Constants.REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME, refreshToken);
+ params.put(Constants.SCOPE_PARAM_NAME, Constants.SCOPES);
+ return getToken(params, consumerKey, consumerSecret);
+ }
+
+ public AccessTokenInfo getToken(JSONObject nameValuePairs, String clientId, String clientSecret)
+ throws APIServicesException {
+
+ String tokenEndPoint = config.getFirstProperty(Constants.TOKE_END_POINT);
+
+ RequestBody requestBody = RequestBody.Companion.create(nameValuePairs.toString(), JSON);
+ Request request = new Request.Builder()
+ .url(tokenEndPoint)
+ .addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(clientId, clientSecret))
+ .post(requestBody)
+ .build();
+
+ try {
+ Response response = client.newCall(request).execute();
+ return gson.fromJson(response.body().string(), AccessTokenInfo.class);
+ } catch (IOException e) {
+ msg = "Error occurred while processing the response";
+ log.error(msg, e);
+ throw new APIServicesException(e);
+ }
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServices.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServices.java
new file mode 100644
index 00000000000..2ea0a51f344
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServices.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api;
+
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
+import org.json.JSONObject;
+import org.wso2.carbon.apimgt.api.model.Scope;
+
+public interface PublisherRESTAPIServices {
+
+ JSONObject getScopes(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException;
+
+ boolean isSharedScopeNameExists(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String key)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException;
+
+ boolean updateSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException;
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServicesImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServicesImpl.java
new file mode 100644
index 00000000000..819b91210d4
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/PublisherRESTAPIServicesImpl.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api;
+
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.ScopeUtils;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.RequestBody;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.ssl.Base64;
+import org.json.JSONObject;
+import org.wso2.carbon.apimgt.api.model.Scope;
+
+import java.io.IOException;
+
+public class PublisherRESTAPIServicesImpl implements PublisherRESTAPIServices {
+ private static final Log log = LogFactory.getLog(PublisherRESTAPIServicesImpl.class);
+ private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ private static final String host = System.getProperty(Constants.IOT_CORE_HOST);
+ private static final String port = System.getProperty(Constants.IOT_CORE_HTTPS_PORT);
+
+ @Override
+ public JSONObject getScopes(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException {
+
+ String getAllScopesUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host + Constants.COLON
+ + port + Constants.GET_ALL_SCOPES;
+ Request request = new Request.Builder()
+ .url(getAllScopesUrl)
+ .addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ + accessTokenInfo.getAccess_token())
+ .get()
+ .build();
+
+ try {
+ Response response = client.newCall(request).execute();
+ if (HttpStatus.SC_OK == response.code()) {
+ JSONObject jsonObject = new JSONObject(response.body().string());
+ return jsonObject;
+ } else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
+ APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
+ AccessTokenInfo refreshedAccessToken = apiApplicationServices.
+ generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
+ apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
+ //TODO: max attempt count
+ return getScopes(apiApplicationKey, refreshedAccessToken);
+ } else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
+ String msg = "Bad Request, Invalid request";
+ log.error(msg);
+ throw new BadRequestException(msg);
+ } else {
+ String msg = "Response : " + response.code() + response.body();
+ throw new UnexpectedResponseException(msg);
+ }
+ } catch (IOException e) {
+ String msg = "Error occurred while processing the response";
+ log.error(msg, e);
+ throw new APIServicesException(e);
+ }
+ }
+
+ @Override
+ public boolean isSharedScopeNameExists(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String key)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException {
+
+ String keyValue = new String(Base64.encodeBase64((key).getBytes())).replace(Constants.QUERY_KEY_VALUE_SEPARATOR,
+ Constants.EMPTY_STRING);
+ String getScopeUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host + Constants.COLON
+ + port + Constants.GET_SCOPE + keyValue;
+
+ Request request = new Request.Builder()
+ .url(getScopeUrl)
+ .addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ + accessTokenInfo.getAccess_token())
+ .head()
+ .build();
+ try {
+ Response response = client.newCall(request).execute();
+ if (HttpStatus.SC_OK == response.code()) {
+ return true;
+ } else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
+ APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
+ AccessTokenInfo refreshedAccessToken = apiApplicationServices.
+ generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
+ apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
+ //TODO: max attempt count
+ return isSharedScopeNameExists(apiApplicationKey, refreshedAccessToken, key);
+ } else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
+ String msg = "Bad Request, Invalid request";
+ log.error(msg);
+ throw new BadRequestException(msg);
+ } else {
+ String msg = "Response : " + response.code() + response.body();
+ throw new UnexpectedResponseException(msg);
+ }
+ } catch (IOException e) {
+ String msg = "Error occurred while processing the response";
+ log.error(msg, e);
+ throw new APIServicesException(e);
+ }
+ }
+
+ @Override
+ public boolean updateSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
+ throws APIServicesException, BadRequestException, UnexpectedResponseException {
+
+ String updateScopeUrl = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host
+ + Constants.COLON + port + Constants.GET_SCOPE + scope.getId();
+
+ ScopeUtils scopeUtil = new ScopeUtils();
+ scopeUtil.setKey(scope.getKey());
+ scopeUtil.setName(scope.getName());
+ scopeUtil.setDescription(scope.getDescription());
+ scopeUtil.setRoles(scope.getRoles());
+ String scopeString = scopeUtil.toJSON();
+
+ RequestBody requestBody = RequestBody.create(JSON, scopeString);
+ Request request = new Request.Builder()
+ .url(updateScopeUrl)
+ .addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ + accessTokenInfo.getAccess_token())
+ .put(requestBody)
+ .build();
+
+ try {
+ Response response = client.newCall(request).execute();
+ if (HttpStatus.SC_OK == response.code()) {
+ return true;
+ } else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
+ APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
+ AccessTokenInfo refreshedAccessToken = apiApplicationServices.
+ generateAccessTokenFromRefreshToken(accessTokenInfo.getRefresh_token(),
+ apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
+ //TODO: max attempt count
+ return updateSharedScope(apiApplicationKey, refreshedAccessToken, scope);
+ } else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
+ String msg = "Bad Request, Invalid scope object";
+ log.error(msg);
+ throw new BadRequestException(msg);
+ } else {
+ String msg = "Response : " + response.code() + response.body();
+ throw new UnexpectedResponseException(msg);
+ }
+ } catch (IOException e) {
+ String msg = "Error occurred while processing the response";
+ log.error(msg, e);
+ throw new APIServicesException(e);
+ }
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/bean/RegistrationProfile.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/bean/RegistrationProfile.java
new file mode 100644
index 00000000000..455c4704d1a
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/bean/RegistrationProfile.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.bean;
+
+/**
+ * This class represents the data that are required to register
+ * the oauth application.
+ */
+public class RegistrationProfile {
+
+ private String callbackUrl;
+ private String clientName;
+ private String tokenScope;
+ private String owner;
+ private String grantType;
+ private String applicationType;
+ private boolean isSaasApp;
+
+ private static final String TAG = RegistrationProfile.class.getSimpleName();
+
+ public String getCallbackUrl() {
+ return callbackUrl;
+ }
+
+ public void setCallbackUrl(String callBackUrl) {
+ this.callbackUrl = callBackUrl;
+ }
+
+ public String getClientName() {
+ return clientName;
+ }
+
+ public void setClientName(String clientName) {
+ this.clientName = clientName;
+ }
+
+ public String getTokenScope() {
+ return tokenScope;
+ }
+
+ public void setTokenScope(String tokenScope) {
+ this.tokenScope = tokenScope;
+ }
+
+ public String getOwner() {
+ return owner;
+ }
+
+ public void setOwner(String owner) {
+ this.owner = owner;
+ }
+
+ public String getGrantType() {
+ return grantType;
+ }
+
+ public void setGrantType(String grantType) {
+ this.grantType = grantType;
+ }
+
+ public String getApplicationType() {
+ return applicationType;
+ }
+
+ public void setApplicationType(String applicationType) {
+ this.applicationType = applicationType;
+ }
+
+ public boolean isSaasApp() {
+ return isSaasApp;
+ }
+
+ public void setIsSaasApp(boolean isSaasApp) {
+ this.isSaasApp = isSaasApp;
+ }
+
+ public String toJSON() {
+ String jsonString =
+ "{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName +
+ "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
+ "\", \"saasApp\" : " + isSaasApp + " }\n";
+ return jsonString;
+ }
+}
\ No newline at end of file
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java
new file mode 100644
index 00000000000..e4dd49b3818
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.constants;
+
+public final class Constants {
+
+ private Constants() {
+ }
+
+ public static final String EMPTY_STRING = "";
+ public static final String CLIENT_NAME = "rest_api_publisher_code";
+ public static final String SERVER_USER = "WorkflowConfigurations.ServerUser";
+ public static final String SERVER_PASSWORD = "WorkflowConfigurations.ServerPassword";
+ public static final String GRANT_TYPE = "client_credentials password refresh_token";
+ public static final String REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME = "refresh_token";
+ public static final String OAUTH_EXPIRES_IN = "expires_in";
+ public static final String OAUTH_TOKEN_SCOPE = "scope";
+ public static final String OAUTH_TOKEN_TYPE = "token_type";
+ public static final String REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
+ public static final String SCOPE_PARAM_NAME = "scope";
+ public static final String SCOPES = "apim:api_create apim:api_view apim:shared_scope_manage";
+ public static final String DCR_END_POINT = "WorkflowConfigurations.DCREndPoint";
+ public static final String TOKE_END_POINT = "WorkflowConfigurations.TokenEndPoint";
+ public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
+ public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
+ public static final String CLIENT_ID = "clientId";
+ public static final String CLIENT_SECRET = "clientSecret";
+
+ public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
+ public static final String AUTHORIZATION_HEADER_VALUE_PREFIX = "Basic ";
+ public static final String AUTHORIZATION_HEADER_PREFIX_BEARER = "Bearer ";
+ public static final String HEADER_CONTENT_TYPE = "Content-Type";
+ public static final String APPLICATION_JSON = "application/json";
+ public static final String PASSWORD_GRANT_TYPE = "password";
+ public static final String PASSWORD_GRANT_TYPE_USERNAME = "username";
+ public static final String PASSWORD_GRANT_TYPE_PASSWORD = "password";
+ public static final String PASSWORD_GRANT_TYPE_SCOPES = "scopes";
+ public static final String ACCESS_TOKEN_GRANT_TYPE_PARAM_NAME = "access_token";
+ public static final String GRANT_TYPE_PARAM_NAME = "grant_type";
+ public static final String HTTPS_PROTOCOL = "https";
+ public static final String HTTP_PROTOCOL = "http";
+ public static final String SCHEME_SEPARATOR = "://";
+ public static final String COLON = ":";
+ public static final String QUERY_KEY_VALUE_SEPARATOR = "=";
+ public static final String IOT_CORE_HOST = "iot.core.host";
+ public static final String IOT_CORE_HTTPS_PORT = "iot.core.https.port";
+ public static final String GET_ALL_SCOPES = "/api/am/publisher/v2/scopes?limit=1000";
+ public static final String GET_SCOPE = "/api/am/publisher/v2/scopes/";
+}
+
+
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/APIApplicationKey.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/APIApplicationKey.java
new file mode 100644
index 00000000000..a4b4660bb8c
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/APIApplicationKey.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.dto;
+
+/**
+ * This holds the consumer application information that return from the register application endpoint
+ */
+public class APIApplicationKey {
+ private String clientName;
+ private String clientId;
+ private String clientSecret;
+ private String callBackURL;
+ private String isSaasApplication;
+ private String appOwner;
+ private String jsonString;
+ private String jsonAppAttribute;
+ private String tokenType;
+
+ public APIApplicationKey(String clientId, String clientSecret) {
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getClientName() {
+ return clientName;
+ }
+
+ public void setClientName(String clientName) {
+ this.clientName = clientName;
+ }
+
+
+ public String getCallBackURL() {
+ return callBackURL;
+ }
+
+ public void setCallBackURL(String callBackURL) {
+ this.callBackURL = callBackURL;
+ }
+
+ public String getIsSaasApplication() {
+ return isSaasApplication;
+ }
+
+ public void setIsSaasApplication(String isSaasApplication) {
+ this.isSaasApplication = isSaasApplication;
+ }
+
+ public String getAppOwner() {
+ return appOwner;
+ }
+
+ public void setAppOwner(String appOwner) {
+ this.appOwner = appOwner;
+ }
+
+ public String getJsonString() {
+ return jsonString;
+ }
+
+ public void setJsonString(String jsonString) {
+ this.jsonString = jsonString;
+ }
+
+ public String getJsonAppAttribute() {
+ return jsonAppAttribute;
+ }
+
+ public void setJsonAppAttribute(String jsonAppAttribute) {
+ this.jsonAppAttribute = jsonAppAttribute;
+ }
+
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ public void setTokenType(String tokenType) {
+ this.tokenType = tokenType;
+ }
+
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/AccessTokenInfo.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/AccessTokenInfo.java
new file mode 100644
index 00000000000..95bc2b34ba4
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/dto/AccessTokenInfo.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.dto;
+
+/**
+ * This holds the token information that return from the token endpoint.
+ */
+public class AccessTokenInfo {
+
+ private String token_type;
+ private long expires_in;
+ private String refresh_token;
+ private String access_token;
+ private String scope;
+
+ public String getToken_type() {
+ return token_type;
+ }
+
+ public void setToken_type(String token_type) {
+ this.token_type = token_type;
+ }
+
+ public long getExpires_in() {
+ return expires_in;
+ }
+
+ public void setExpires_in(long expires_in) {
+ this.expires_in = expires_in;
+ }
+
+ public String getRefresh_token() {
+ return refresh_token;
+ }
+
+ public void setRefresh_token(String refresh_token) {
+ this.refresh_token = refresh_token;
+ }
+
+ public String getAccess_token() {
+ return access_token;
+ }
+
+ public void setAccess_token(String access_token) {
+ this.access_token = access_token;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/APIServicesException.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/APIServicesException.java
new file mode 100644
index 00000000000..3b9c4cfc7d2
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/APIServicesException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
+
+public class APIServicesException extends Exception {
+
+ public APIServicesException() {
+ super();
+ }
+
+ public APIServicesException(String message) {
+ super(message);
+ }
+
+ public APIServicesException(String message, Throwable cause) {
+ super(message);
+ }
+
+ public APIServicesException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/BadRequestException.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/BadRequestException.java
new file mode 100644
index 00000000000..6aa9be1130c
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/BadRequestException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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.
+ */
+
+/**
+ * Custom exception class for handling bad request exceptions.
+ */
+package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
+
+public class BadRequestException extends Exception {
+
+ private static final long serialVersionUID = -2387103750774855056L;
+
+ public BadRequestException(String errorMessage) {
+ super(errorMessage);
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/UnexpectedResponseException.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/UnexpectedResponseException.java
new file mode 100644
index 00000000000..898caba26e8
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/exceptions/UnexpectedResponseException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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.
+ */
+
+/**
+ * Custom exception class for handling unexpected server response exceptions.
+ */
+package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
+
+public class UnexpectedResponseException extends Exception {
+
+ private static final long serialVersionUID = -2387103750774855056L;
+
+ public UnexpectedResponseException(String errorMessage) {
+ super(errorMessage);
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIDataHolder.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIDataHolder.java
new file mode 100644
index 00000000000..18398af9d54
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIDataHolder.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.internal;
+
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
+import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
+
+public class PublisherRESTAPIDataHolder {
+
+ private APIApplicationServices apiApplicationServices;
+ private APIManagerConfigurationService apiManagerConfigurationService;
+
+ private static PublisherRESTAPIDataHolder thisInstance = new PublisherRESTAPIDataHolder();
+
+ private PublisherRESTAPIDataHolder() {
+ }
+
+ static PublisherRESTAPIDataHolder getInstance() {
+ return thisInstance;
+ }
+
+ public APIApplicationServices getApiApplicationServices() {
+ return apiApplicationServices;
+ }
+
+ public void setApiApplicationServices(APIApplicationServices apiApplicationServices) {
+ this.apiApplicationServices = apiApplicationServices;
+ }
+
+ public void setAPIManagerConfiguration(APIManagerConfigurationService apiManagerConfigurationService) {
+ this.apiManagerConfigurationService = apiManagerConfigurationService;
+ }
+
+ public APIManagerConfigurationService getAPIManagerConfigurationService() {
+ if (apiManagerConfigurationService == null) {
+ throw new IllegalStateException("API Manager Configuration service is not initialized properly");
+ }
+ return apiManagerConfigurationService;
+ }
+
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIServiceComponent.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIServiceComponent.java
new file mode 100644
index 00000000000..989a5477299
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/internal/PublisherRESTAPIServiceComponent.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.internal;
+
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
+
+/**
+ * @scr.component name="internal.io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServiceComponent"
+ * immediate="true"
+ * @scr.reference name="user.apimanagerconfigurationservice.default"
+ * interface="org.wso2.carbon.apimgt.impl.APIManagerConfigurationService"
+ * cardinality="1..1"
+ * policy="dynamic"
+ * bind="setAPIManagerConfigurationService"
+ * unbind="unsetAPIManagerConfigurationService"
+ */
+public class PublisherRESTAPIServiceComponent {
+
+ private static Log log = LogFactory.getLog(PublisherRESTAPIServiceComponent.class);
+
+ protected void activate(ComponentContext componentContext) {
+ if (log.isDebugEnabled()) {
+ log.debug("Initializing publisher API extension bundle");
+ }
+ try {
+ BundleContext bundleContext = componentContext.getBundleContext();
+
+ APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
+ bundleContext.registerService(APIApplicationServices.class.getName(), apiApplicationServices, null);
+ PublisherRESTAPIDataHolder.getInstance().setApiApplicationServices(apiApplicationServices);
+
+ if (log.isDebugEnabled()) {
+ log.debug("API Application bundle has been successfully initialized");
+ }
+ } catch (Exception e) {
+ log.error("Error occurred while initializing API Application bundle", e);
+ }
+ }
+
+ protected void deactivate(ComponentContext componentContext) {
+ //do nothing
+ }
+
+ protected void setAPIManagerConfigurationService(APIManagerConfigurationService apiManagerConfigurationService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Setting API Manager Configuration Service");
+ }
+ PublisherRESTAPIDataHolder.getInstance().setAPIManagerConfiguration(apiManagerConfigurationService);
+ }
+
+ protected void unsetAPIManagerConfigurationService(APIManagerConfigurationService apiManagerConfigurationService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Unsetting API Manager Configuration Service");
+ }
+ PublisherRESTAPIDataHolder.getInstance().setAPIManagerConfiguration(null);
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/HttpsTrustManagerUtils.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/HttpsTrustManagerUtils.java
new file mode 100644
index 00000000000..b55857af378
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/HttpsTrustManagerUtils.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.util;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.base.ServerConfiguration;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.HostnameVerifier;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.URI;
+
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class HttpsTrustManagerUtils {
+
+ private static final Log log = LogFactory.getLog(HttpsTrustManagerUtils.class);
+ private static final String KEY_STORE_TYPE = "JKS";
+ /**
+ * Default truststore type of the client
+ */
+ private static final String TRUST_STORE_TYPE = "JKS";
+ /**
+ * Default keymanager type of the client
+ */
+ private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type
+ /**
+ * Default trustmanager type of the client
+ */
+ private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type
+ private static final String SSLV3 = "SSLv3";
+ private static final String DEFAULT_HOST = "localhost";
+ private static final String DEFAULT_HOST_IP = "127.0.0.1";
+ private static final int TIMEOUT = 100;
+
+ public static OkHttpClient getSSLClient() {
+
+ boolean isIgnoreHostnameVerification = Boolean.parseBoolean(System.getProperty("org.wso2"
+ + ".ignoreHostnameVerification"));
+ OkHttpClient okHttpClient;
+ final String proxyHost = System.getProperty("http.proxyHost");
+ final String proxyPort = System.getProperty("http.proxyPort");
+ final String nonProxyHostsValue = System.getProperty("http.nonProxyHosts");
+
+ final ProxySelector proxySelector = new ProxySelector() {
+ @Override
+ public List select(URI uri) {
+ List proxyList = new ArrayList<>();
+ String host = uri.getHost();
+
+ if (!StringUtils.isEmpty(host)) {
+ if (host.startsWith(DEFAULT_HOST_IP) || host.startsWith(DEFAULT_HOST) || StringUtils
+ .isEmpty(nonProxyHostsValue) || StringUtils.contains(nonProxyHostsValue, host) ||
+ StringUtils.isEmpty(proxyHost) || StringUtils.isEmpty(proxyPort)) {
+ proxyList.add(Proxy.NO_PROXY);
+ } else {
+ proxyList.add(new Proxy(Proxy.Type.HTTP,
+ new InetSocketAddress(proxyHost, Integer.parseInt(proxyPort))));
+ }
+ } else {
+ log.error("Host is null. Host could not be empty or null");
+ }
+ return proxyList;
+ }
+
+ @Override
+ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ };
+
+ X509TrustManager trustAllCerts = new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return new java.security.cert.X509Certificate[0];
+ }
+
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs, String authType) {
+ }
+ };
+
+ if (isIgnoreHostnameVerification) {
+ okHttpClient = new OkHttpClient.Builder()
+ .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .readTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .connectionPool(new ConnectionPool(TIMEOUT, TIMEOUT, TimeUnit.SECONDS))
+ .sslSocketFactory(getSimpleTrustedSSLSocketFactory(), trustAllCerts)
+ .hostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ }).proxySelector(proxySelector).build();
+ return okHttpClient;
+ } else {
+ SSLSocketFactory trustedSSLSocketFactory = getTrustedSSLSocketFactory();
+ okHttpClient = new OkHttpClient.Builder()
+ .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .readTimeout(TIMEOUT, TimeUnit.SECONDS)
+ .connectionPool(new ConnectionPool(TIMEOUT, TIMEOUT, TimeUnit.SECONDS))
+ .sslSocketFactory(trustedSSLSocketFactory)
+ .proxySelector(proxySelector).build();
+ return okHttpClient;
+ }
+ }
+
+ private static SSLSocketFactory getSimpleTrustedSSLSocketFactory() {
+ try {
+ TrustManager[] trustAllCerts = new TrustManager[]{
+ new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs, String authType) {
+ }
+ }
+ };
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, trustAllCerts, new SecureRandom());
+ return sc.getSocketFactory();
+ } catch (KeyManagementException | NoSuchAlgorithmException e) {
+ log.error("Error while creating the SSL socket factory due to " + e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private static SSLSocketFactory getTrustedSSLSocketFactory() {
+ try {
+ String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password");
+ String keyStoreLocation = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Location");
+ String trustStorePassword = ServerConfiguration.getInstance().getFirstProperty(
+ "Security.TrustStore.Password");
+ String trustStoreLocation = ServerConfiguration.getInstance().getFirstProperty(
+ "Security.TrustStore.Location");
+ KeyStore keyStore = loadKeyStore(keyStoreLocation, keyStorePassword, KEY_STORE_TYPE);
+ KeyStore trustStore = loadTrustStore(trustStoreLocation, trustStorePassword);
+
+ return initSSLConnection(keyStore, keyStorePassword, trustStore);
+ } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException
+ | CertificateException | IOException | UnrecoverableKeyException e) {
+ log.error("Error while creating the SSL socket factory due to " + e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private static SSLSocketFactory initSSLConnection(KeyStore keyStore, String keyStorePassword, KeyStore trustStore)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException {
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
+ keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
+ trustManagerFactory.init(trustStore);
+
+ // Create and initialize SSLContext for HTTPS communication
+ SSLContext sslContext = SSLContext.getInstance(SSLV3);
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ SSLContext.setDefault(sslContext);
+ return sslContext.getSocketFactory();
+ }
+
+ private static KeyStore loadKeyStore(String keyStorePath, String ksPassword, String type)
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+ InputStream fileInputStream = null;
+ try {
+ char[] keypassChar = ksPassword.toCharArray();
+ KeyStore keyStore = KeyStore.getInstance(type);
+ fileInputStream = new FileInputStream(keyStorePath);
+ keyStore.load(fileInputStream, keypassChar);
+ return keyStore;
+ } finally {
+ if (fileInputStream != null) {
+ fileInputStream.close();
+ }
+ }
+ }
+
+ private static KeyStore loadTrustStore(String trustStorePath, String tsPassword)
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+ return loadKeyStore(trustStorePath, tsPassword, TRUST_STORE_TYPE);
+ }
+}
diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/ScopeUtils.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/ScopeUtils.java
new file mode 100644
index 00000000000..18944c945c6
--- /dev/null
+++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/util/ScopeUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.extension.rest.api.util;
+
+/**
+ * This class represents the scope data.
+ */
+public class ScopeUtils {
+
+ private String key;
+ private String name;
+ private String roles;
+ private String description;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getRoles() {
+ return roles;
+ }
+
+ public void setRoles(String roles) {
+ this.roles = roles;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String toJSON() {
+ String jsonString = "{\n" +
+ " \"name\":\" " + key + "\",\n" +
+ " \"displayName\":\" " + name + "\",\n" +
+ " \"description\":\" " + description + " \",\n" +
+ " \"bindings\":[\n" +
+ " \" " + roles + " \"\n" +
+ " ]\n" +
+ "}";
+ return jsonString;
+ }
+}
\ No newline at end of file
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml
index 25fa414b151..21c7df3235b 100644
--- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml
@@ -122,6 +122,15 @@
h2-database-engine
test
+
+ org.wso2.carbon.devicemgt
+ io.entgra.device.mgt.core.apimgt.extension.rest.api
+ provided
+
+
+ org.json.wso2
+ json
+
@@ -165,6 +174,9 @@
org.scannotation;version="1.0",
org.scannotation.archiveiterator;version="1.0",
org.w3c.dom,
+ io.entgra.device.mgt.core.apimgt.extension.rest.api,
+ io.entgra.device.mgt.core.apimgt.extension.rest.api.dto,
+ io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions,
org.wso2.carbon.apimgt.annotations.api,
org.wso2.carbon.apimgt.api,
org.wso2.carbon.apimgt.api.model,
@@ -187,7 +199,8 @@
org.wso2.carbon.utils;version="4.6",
org.wso2.carbon.utils.multitenancy;version="4.6",
org.wso2.carbon.apimgt.impl.definitions,
- org.apache.commons.lang
+ org.apache.commons.lang,
+ org.json
jsr311-api;scope=compile|runtime;inline=false
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 0dcc92e6381..0725998e7f2 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
@@ -18,11 +18,22 @@
*/
package org.wso2.carbon.apimgt.webapp.publisher;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServicesImpl;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
+import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.model.Documentation;
import org.wso2.carbon.apimgt.api.model.DocumentationType;
+import org.json.JSONArray;
+import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIProvider;
import org.wso2.carbon.apimgt.api.FaultGatewaysException;
@@ -50,7 +61,6 @@ import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantSearchResult;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
-import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.BufferedReader;
import java.io.File;
@@ -357,13 +367,26 @@ public class APIPublisherServiceImpl implements APIPublisherService {
WebappPublisherConfig config = WebappPublisherConfig.getInstance();
List tenants = new ArrayList<>(Collections.singletonList(APIConstants.SUPER_TENANT_DOMAIN));
tenants.addAll(config.getTenants().getTenant());
+
+ APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
+ APIApplicationKey apiApplicationKey;
+ AccessTokenInfo accessTokenInfo;
+ try {
+ apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials();
+ accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
+ apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
+ } catch (APIServicesException e) {
+ String errorMsg = "Error while generating application";
+ log.error(errorMsg, e);
+ throw new APIManagerPublisherException(e);
+ }
+
try {
for (String tenantDomain : tenants) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
- APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(MultitenantUtils.getTenantAwareUsername(
- PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
- .getAdminUserName()));
+ PublisherRESTAPIServices publisherRESTAPIServices = new PublisherRESTAPIServicesImpl();
+ JSONObject scopeObject = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
try {
String fileName =
@@ -409,8 +432,18 @@ public class APIPublisherServiceImpl implements APIPublisherService {
}
scope.setRoles(roleString);
- if (apiProvider.isSharedScopeNameExists(scope.getKey(), tenantDomain)) {
- apiProvider.updateSharedScope(scope, tenantDomain);
+ //Set scope id which related to the scope key
+ JSONArray scopeList = (JSONArray) scopeObject.get("list");
+ for (int i = 0; i < scopeList.length(); i++) {
+ JSONObject scopeObj = scopeList.getJSONObject(i);
+ if (scopeObj.getString("name").equals(scopeMapping[2] != null ?
+ StringUtils.trim(scopeMapping[2]) : StringUtils.EMPTY)) {
+ scope.setId(scopeObj.getString("id"));
+ }
+ }
+
+ if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getKey())) {
+ publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope);
} else {
// todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list
if (log.isDebugEnabled()) {
@@ -421,18 +454,27 @@ public class APIPublisherServiceImpl implements APIPublisherService {
}
} catch (IOException | DirectoryIteratorException ex) {
log.error("failed to read scopes from file.", ex);
+ } catch (APIServicesException | BadRequestException e) {
+ String errorMsg = "Error while calling APIs";
+ log.error(errorMsg, e);
+ throw new APIManagerPublisherException(e);
}
}
- } catch (UserStoreException e) {
- String msg = "Error occurred while reading tenant admin username";
- log.error(msg, e);
+ }
+ catch (APIServicesException e) {
+ String errorMsg = "Error while processing Publisher REST API response";
+ log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
- } catch (APIManagementException e) {
- String msg = "Error occurred while loading api provider";
- log.error(msg, e);
+ } catch (BadRequestException e) {
+ String errorMsg = "Error while calling Publisher REST APIs";
+ log.error(errorMsg, e);
+ throw new APIManagerPublisherException(e);
+ } catch (UnexpectedResponseException e) {
+ String errorMsg = "Unexpected response from the server";
+ log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
- } finally {
+ }finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
diff --git a/components/apimgt-extensions/pom.xml b/components/apimgt-extensions/pom.xml
index c877688505d..c2586135daf 100644
--- a/components/apimgt-extensions/pom.xml
+++ b/components/apimgt-extensions/pom.xml
@@ -40,6 +40,7 @@
org.wso2.carbon.apimgt.keymgt.extension
org.wso2.carbon.apimgt.keymgt.extension.api
io.entgra.device.mgt.core.apimgt.analytics.extension
+ io.entgra.device.mgt.core.apimgt.extension.rest.api
diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/pom.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/pom.xml
index b6344f6e454..de2739b1995 100644
--- a/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/pom.xml
+++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/pom.xml
@@ -51,6 +51,10 @@
io.swagger
swagger-annotations
+
+ org.wso2.carbon.devicemgt
+ io.entgra.device.mgt.core.apimgt.extension.rest.api
+
@@ -143,6 +147,9 @@
io.swagger:swagger-annotations:${swagger.version}
+
+ org.wso2.carbon.devicemgt:io.entgra.device.mgt.core.apimgt.extension.rest.api:${carbon.device.mgt.version}
+
org.wso2.carbon.core.server:${carbon.kernel.version}
diff --git a/pom.xml b/pom.xml
index b61ce5221b3..e9686004167 100644
--- a/pom.xml
+++ b/pom.xml
@@ -238,6 +238,11 @@
org.wso2.carbon.apimgt.annotations
${carbon.device.mgt.version}
+
+ org.wso2.carbon.devicemgt
+ io.entgra.device.mgt.core.apimgt.extension.rest.api
+ ${carbon.device.mgt.version}
+
org.wso2.carbon.devicemgt
org.wso2.carbon.device.mgt.oauth.extensions