From e1b423e9bd9383f9dc8ced62645c8617040a2eab Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 13 Mar 2023 15:10:26 +0530 Subject: [PATCH 01/38] ResourcePath and ResourceMethod added to loggingApiInput Schema --- .../src/main/resources/devops-api.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml index 334746eead61..33e744c0768f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml @@ -234,10 +234,18 @@ components: LoggingApiInput: title: API Info object with log details + required: + - logLevel properties: logLevel: type: string example: FULL + resourceMethod: + type: string + example: GET + resourcePath: + type: string + example: /v1.0.0/pizza LoggingApiOutput: title: API Info object with log details properties: From d57654e3cb1222795ee2cfd4b22f88cd0a12d8ae Mon Sep 17 00:00:00 2001 From: shnrndk Date: Fri, 17 Mar 2023 15:03:52 +0530 Subject: [PATCH 02/38] Moved log_level field from AM_API to AM_API_URL_MAPPING. --- .../impl/dao/constants/SQLConstants.java | 23 +++++++------------ .../src/main/resources/sql/h2.sql | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) 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 5fb9f1fc2ec9..b2560ab96fbe 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 @@ -3011,28 +3011,21 @@ public class SQLConstants { public static final String RESTORE_API_REVISION_METADATA = "UPDATE AM_API SET API_TIER = (SELECT API_TIER FROM " + "AM_API_REVISION_METADATA WHERE API_UUID = ? AND REVISION_UUID = ?) WHERE API_UUID = ?"; public static final String ADD_PER_API_LOGGING_SQL = - "UPDATE AM_API SET LOG_LEVEL=? WHERE API_UUID=? AND ORGANIZATION=?"; + "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?)"; public static final String RETRIEVE_PER_API_LOGGING_OFF_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION=?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION=?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_STANDARD_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION=?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_FULL_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION=?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_ALL_PER_API_LOGGING_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_PER_API_LOGGING_ALL_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.ORGANIZATION=?"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BY_UUID_SQL = - "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + - "FROM AM_API WHERE AM_API.API_UUID = ? AND AM_API.ORGANIZATION=?"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.API_UUID = ? AND API.ORGANIZATION= ?"; public static final String GATEWAY_LABEL_REGEX = "_GATEWAY_LABELS_"; public static final String API_ID_REGEX = "_API_IDS_"; public static final String API_UUID_REGEX = "_API_UUIDS_"; diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index 269961048c87..ac6883edc97b 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1547,7 +1547,6 @@ CREATE TABLE IF NOT EXISTS AM_API ( REVISIONS_CREATED INTEGER DEFAULT 0, STATUS VARCHAR(30), VERSION_COMPARABLE VARCHAR(15), - LOG_LEVEL VARCHAR(255) DEFAULT 'OFF', UNIQUE (API_UUID), UNIQUE (API_PROVIDER,API_NAME,API_VERSION,ORGANIZATION) ); @@ -1573,6 +1572,7 @@ CREATE TABLE IF NOT EXISTS AM_API_URL_MAPPING ( THROTTLING_TIER varchar(512) DEFAULT NULL, MEDIATION_SCRIPT BLOB DEFAULT NULL, REVISION_UUID VARCHAR(256), + LOG_LEVEL VARCHAR(255) DEFAULT 'OFF', PRIMARY KEY(URL_MAPPING_ID) ); From 1de92127782846188e3d49bc46d8cc4b5741a2e9 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Thu, 23 Mar 2023 09:52:34 +0530 Subject: [PATCH 03/38] log level field added to am_api also to work with both tables. --- .../devops/impl/logging/APILoggingImpl.java | 16 +++++++++++-- .../carbon/apimgt/impl/dao/LoggingMgtDAO.java | 23 +++++++++++++++++++ .../impl/dao/constants/SQLConstants.java | 4 +++- .../devops/impl/TenantLogsApiServiceImpl.java | 3 ++- .../src/main/resources/sql/h2.sql | 1 + 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java index 50cf5978648f..49aaa17a034e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java @@ -38,9 +38,11 @@ public class APILoggingImpl { private static final String PER_API_LOGGING_PERMISSION_PATH = "/permission/protected/configure/logging"; private static final String INVALID_LOGGING_PERMISSION = "Invalid logging permission"; + private static final String INCORRECT_LOGGING_PER_API_RESOURCE_REQUEST = "Resource Method and Resource Path both should included"; private final ApiMgtDAO apiMgtDAO = ApiMgtDAO.getInstance(); - public void addUpdateAPILogger(String tenantId, String apiId, String logLevel) throws APIManagementException { + public void addUpdateAPILogger(String tenantId, String apiId, String logLevel, String resourceMethod, + String resourcePath) throws APIManagementException { if (apiMgtDAO.getAPIInfoByUUID(apiId) == null) { throw new APIManagementException("API not found.", ExceptionCodes.from(ExceptionCodes.API_NOT_FOUND, apiId)); @@ -49,7 +51,17 @@ public void addUpdateAPILogger(String tenantId, String apiId, String logLevel) t throw new APIManagementException(INVALID_LOGGING_PERMISSION, ExceptionCodes.from(ExceptionCodes.INVALID_PERMISSION)); } - LoggingMgtDAO.getInstance().addAPILogger(tenantId, apiId, logLevel); + + if (resourceMethod != null && resourcePath != null) { + LoggingMgtDAO.getInstance().addAPILoggerPerResource(tenantId, apiId, logLevel, resourceMethod.toUpperCase(), + resourcePath); + } else if (resourceMethod == null && resourcePath == null) { + LoggingMgtDAO.getInstance().addAPILogger(tenantId, apiId, logLevel); + } else { + throw new APIManagementException(INCORRECT_LOGGING_PER_API_RESOURCE_REQUEST, + ExceptionCodes.from(ExceptionCodes.LOGGING_API_MISSING_DATA)); + } + publishLogAPIData(tenantId, apiId, logLevel); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index df2f8b82faab..0fbf87a6bd3b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -76,6 +76,29 @@ public void addAPILogger(String organization, String apiId, String logLevel) thr } } + public void addAPILoggerPerResource(String organization, String apiId, String logLevel, String resourceMethod, + String resourcePath) throws APIManagementException { + try (Connection addLoggingCon = APIMgtDBUtil.getConnection()) { + addLoggingCon.setAutoCommit(false); + try (PreparedStatement preparedStatement = addLoggingCon.prepareStatement( + SQLConstants.ADD_PER_API_RESOURCE_LOGGING_SQL)) { + preparedStatement.setString(1, logLevel); + preparedStatement.setString(2, apiId); + preparedStatement.setString(3, organization); + preparedStatement.setString(4, resourceMethod); + preparedStatement.setString(5, resourcePath); + + preparedStatement.executeUpdate(); + addLoggingCon.commit(); + } catch (SQLException e) { + addLoggingCon.rollback(); + throw new ApiLoggingMgtException("Error while adding new per API logger", e); + } + } catch (SQLException e) { + handleException("Failed to add API logging for " + apiId + " with the log level " + logLevel, e); + } + } + public List retrieveAPILoggerList(String organization, String logLevel) throws APIManagementException { List apiLogInfoDTOList = new ArrayList<>(); 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 b2560ab96fbe..440d7a2680c1 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 @@ -3011,7 +3011,9 @@ public class SQLConstants { public static final String RESTORE_API_REVISION_METADATA = "UPDATE AM_API SET API_TIER = (SELECT API_TIER FROM " + "AM_API_REVISION_METADATA WHERE API_UUID = ? AND REVISION_UUID = ?) WHERE API_UUID = ?"; public static final String ADD_PER_API_LOGGING_SQL = - "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?)"; + "UPDATE AM_API SET LOG_LEVEL=? WHERE API_UUID=? AND ORGANIZATION=?"; + public static final String ADD_PER_API_RESOURCE_LOGGING_SQL = + "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; public static final String RETRIEVE_PER_API_LOGGING_OFF_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/impl/TenantLogsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/impl/TenantLogsApiServiceImpl.java index e257e2ecb333..75d6429a4bec 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/impl/TenantLogsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/impl/TenantLogsApiServiceImpl.java @@ -50,7 +50,8 @@ public Response tenantLogsTenantIdApisApiIdPut(String tenantId, String apiId, Lo if (apiId != null) { if (DevopsAPIUtils.validateLogLevel(loggingApiInputDTO.getLogLevel())) { APILoggingImpl apiLoggingImpl = new APILoggingImpl(); - apiLoggingImpl.addUpdateAPILogger(tenantId, apiId, loggingApiInputDTO.getLogLevel().toUpperCase()); + apiLoggingImpl.addUpdateAPILogger(tenantId, apiId, loggingApiInputDTO.getLogLevel().toUpperCase(), + loggingApiInputDTO.getResourceMethod(),loggingApiInputDTO.getResourcePath()); return Response.ok().entity(loggingApiInputDTO).build(); } else { throw new APIManagementException("The input log level is incorrect: Input log level : " + diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index ac6883edc97b..773d7dc645d0 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1547,6 +1547,7 @@ CREATE TABLE IF NOT EXISTS AM_API ( REVISIONS_CREATED INTEGER DEFAULT 0, STATUS VARCHAR(30), VERSION_COMPARABLE VARCHAR(15), + LOG_LEVEL VARCHAR(255) DEFAULT 'OFF', UNIQUE (API_UUID), UNIQUE (API_PROVIDER,API_NAME,API_VERSION,ORGANIZATION) ); From d69f1b12bed89e8c9613ddedfb8beab9731f73c4 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Fri, 24 Mar 2023 17:41:03 +0530 Subject: [PATCH 04/38] changed the get apis related api logging to support with the two tables. --- .../wso2/carbon/apimgt/impl/APIConstants.java | 3 +- .../carbon/apimgt/impl/dao/LoggingMgtDAO.java | 101 +++++++++++++++--- .../impl/dao/constants/SQLConstants.java | 23 +++- .../carbon/apimgt/impl/dto/APILogInfoDTO.java | 18 ++++ .../rest/api/devops/DevopsAPIUtils.java | 2 + .../src/main/resources/devops-api.yaml | 10 ++ 6 files changed, 142 insertions(+), 15 deletions(-) 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 cb6eed462876..6d3399dd2532 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 @@ -2207,7 +2207,8 @@ public enum APITransportType { public static final String LOG_LEVEL_BASIC = "BASIC"; public static final String LOG_LEVEL_STANDARD = "STANDARD"; public static final String LOG_LEVEL_FULL = "FULL"; - + public static final String RESOURCE_METHOD = "HTTP_METHOD"; + public static final String RESOURCE_PATH = "URL_PATTERN"; public static final String PDF_EXTENSION = "pdf"; public static final String XLS_EXTENSION = "xls"; public static final String XLSX_EXTENSION = "xlsx"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index 0fbf87a6bd3b..e677bfed5337 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -102,30 +102,37 @@ public void addAPILoggerPerResource(String organization, String apiId, String lo public List retrieveAPILoggerList(String organization, String logLevel) throws APIManagementException { List apiLogInfoDTOList = new ArrayList<>(); - String query; + String queryPerApi; + String queryPerApiResource; if (logLevel == null) { - query = SQLConstants.RETRIEVE_PER_API_LOGGING_ALL_SQL; + queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_ALL_SQL; + queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_ALL_SQL; } else { switch (logLevel.toUpperCase()) { case APIConstants.LOG_LEVEL_OFF: - query = SQLConstants.RETRIEVE_PER_API_LOGGING_OFF_SQL; + queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_OFF_SQL; + queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_OFF_SQL; break; case APIConstants.LOG_LEVEL_BASIC: - query = SQLConstants.RETRIEVE_PER_API_LOGGING_BASIC_SQL; + queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_BASIC_SQL; + queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_BASIC_SQL; break; case APIConstants.LOG_LEVEL_STANDARD: - query = SQLConstants.RETRIEVE_PER_API_LOGGING_STANDARD_SQL; + queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_STANDARD_SQL; + queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_STANDARD_SQL; break; case APIConstants.LOG_LEVEL_FULL: - query = SQLConstants.RETRIEVE_PER_API_LOGGING_FULL_SQL; + queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_FULL_SQL; + queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_FULL_SQL; break; default: throw new APIManagementException("Invalid log level", ExceptionCodes.from(ExceptionCodes.LOGGING_API_INCORRECT_LOG_LEVEL)); } } + APILogInfoDTO apiLogInfoDTO; try (Connection connection = APIMgtDBUtil.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement(query)) { + PreparedStatement preparedStatement = connection.prepareStatement(queryPerApi)) { preparedStatement.setString(1, organization); try (ResultSet resultSet = preparedStatement.executeQuery()) { while (resultSet.next()) { @@ -133,11 +140,26 @@ public List retrieveAPILoggerList(String organization, String log if (resultSet.getString(APIConstants.LOG_LEVEL) != null) { retrievedLogLevel = resultSet.getString(APIConstants.LOG_LEVEL); } - APILogInfoDTO apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), + apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), resultSet.getString(CONTEXT), retrievedLogLevel); apiLogInfoDTOList.add(apiLogInfoDTO); } } + PreparedStatement preparedStatementResource = connection.prepareStatement(queryPerApiResource); + { + preparedStatementResource.setString(1, organization); + try (ResultSet resultSet = preparedStatementResource.executeQuery()) { + while (resultSet.next()) { + String retrievedLogLevel = APIConstants.LOG_LEVEL_OFF; + if (resultSet.getString(APIConstants.LOG_LEVEL) != null) { + retrievedLogLevel = resultSet.getString(APIConstants.LOG_LEVEL); + } + apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), + resultSet.getString(CONTEXT), retrievedLogLevel); + apiLogInfoDTOList.add(apiLogInfoDTO); + } + } + } } catch (SQLException e) { handleException("Failed to retrieve API logging for organization" + organization, e); } @@ -167,10 +189,13 @@ public List retrieveAllAPILoggerList() throws APIManagementExcept } public List retrieveAPILoggerByAPIID(String tenant, String apiId) throws APIManagementException { - String query = SQLConstants.RETRIEVE_PER_API_LOGGING_BY_UUID_SQL; - List apiLogInfoDTOList = new ArrayList<>(); + String queryPerApi = SQLConstants.RETRIEVE_PER_API_LOGGING_BY_UUID_SQL; + String queryPerApiResource = SQLConstants.RETRIEVE_PER_API_RESOURCE_LOGGING_BY_UUID_SQL; + List apiLogInfoApiDTOList = new ArrayList<>(); + List apiLogInfoApiResourceDTOList = new ArrayList<>(); + List apiHighLogLevelInfoApiResourceDTO = new ArrayList<>(); try (Connection connection = APIMgtDBUtil.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement(query)) { + PreparedStatement preparedStatement = connection.prepareStatement(queryPerApi)) { preparedStatement.setString(1, apiId); preparedStatement.setString(2, tenant); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -181,12 +206,62 @@ public List retrieveAPILoggerByAPIID(String tenant, String apiId) } APILogInfoDTO apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), resultSet.getString(CONTEXT), logLevel); - apiLogInfoDTOList.add(apiLogInfoDTO); + apiLogInfoApiDTOList.add(apiLogInfoDTO); + } + } + PreparedStatement preparedStatementResource = connection.prepareStatement(queryPerApiResource); + { + preparedStatementResource.setString(1, apiId); + preparedStatementResource.setString(2, tenant); + try (ResultSet resultSet = preparedStatementResource.executeQuery()) { + while (resultSet.next()) { + String logLevel = APIConstants.LOG_LEVEL_OFF; + if (resultSet.getString(APIConstants.LOG_LEVEL) != null) { + logLevel = resultSet.getString(APIConstants.LOG_LEVEL); + } + APILogInfoDTO apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), + resultSet.getString(CONTEXT), logLevel, + resultSet.getString(APIConstants.RESOURCE_METHOD), + resultSet.getString(APIConstants.RESOURCE_PATH)); + apiLogInfoApiResourceDTOList.add(apiLogInfoDTO); + } } } } catch (SQLException e) { handleException("Failed to retrieve organization", e); } - return apiLogInfoDTOList; + String apiLogLevel = apiLogInfoApiDTOList.get(0).getLogLevel(); + boolean isResourceLevelHasHighPriority = false; + for (APILogInfoDTO apiLogInfoDTO : apiLogInfoApiResourceDTOList) { + switch (apiLogInfoDTO.getLogLevel()) { + case APIConstants.LOG_LEVEL_FULL: + isResourceLevelHasHighPriority = true; + apiHighLogLevelInfoApiResourceDTO.add(apiLogInfoDTO); + break; + case APIConstants.LOG_LEVEL_STANDARD: + if (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) + || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + isResourceLevelHasHighPriority = true; + apiHighLogLevelInfoApiResourceDTO.add(apiLogInfoDTO); + break; + } else { + break; + } + case APIConstants.LOG_LEVEL_BASIC: + if (apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + isResourceLevelHasHighPriority = true; + apiHighLogLevelInfoApiResourceDTO.add(apiLogInfoDTO); + } else { + break; + } + case APIConstants.LOG_LEVEL_OFF: + break; + } + } + if (isResourceLevelHasHighPriority) { + return apiHighLogLevelInfoApiResourceDTO; + } else { + return apiLogInfoApiDTOList; + } } } 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 440d7a2680c1..49f0b6be6a24 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 @@ -3015,19 +3015,40 @@ public class SQLConstants { public static final String ADD_PER_API_RESOURCE_LOGGING_SQL = "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; public static final String RETRIEVE_PER_API_LOGGING_OFF_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_OFF_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BASIC_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_STANDARD_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_STANDARD_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_FULL_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_FULL_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_ALL_PER_API_LOGGING_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; + public static final String RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL = "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_PER_API_LOGGING_ALL_SQL = + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_ALL_SQL = "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BY_UUID_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.API_UUID = ? AND API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + + "FROM AM_API WHERE AM_API.API_UUID = ? AND AM_API.ORGANIZATION=?"; + public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BY_UUID_SQL = + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, AUM.HTTP_METHOD ,AUM.URL_PATTERN , API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.API_UUID = ? AND API.ORGANIZATION= ?"; public static final String GATEWAY_LABEL_REGEX = "_GATEWAY_LABELS_"; public static final String API_ID_REGEX = "_API_IDS_"; public static final String API_UUID_REGEX = "_API_UUIDS_"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/APILogInfoDTO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/APILogInfoDTO.java index 47ab535021fd..161eacc2b254 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/APILogInfoDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/APILogInfoDTO.java @@ -22,6 +22,8 @@ public class APILogInfoDTO { private String apiId; private String context; private String logLevel; + private String resourceMethod; + private String resourcePath; public APILogInfoDTO(String apiId, String context, String logLevel) { this.apiId = apiId; @@ -29,6 +31,14 @@ public APILogInfoDTO(String apiId, String context, String logLevel) { this.logLevel = logLevel; } + public APILogInfoDTO(String apiId, String context, String logLevel, String resourceMethod, String resourcePath) { + this.apiId = apiId; + this.context = context; + this.logLevel = logLevel; + this.resourceMethod = resourceMethod; + this.resourcePath = resourcePath; + } + public String getApiId() { return apiId; } @@ -52,4 +62,12 @@ public String getLogLevel() { public void setLogLevel(String logLevel) { this.logLevel = logLevel; } + + public String getResourcePath() { return resourcePath;} + + public void setResourcePath(String resourcePath) { this.resourcePath = resourcePath;} + + public String getResourceMethod() { return resourceMethod;} + + public void setResourceMethod(String resourceMethod) { this.resourceMethod = resourceMethod;} } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/DevopsAPIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/DevopsAPIUtils.java index 6c4dab96d7ef..63d3058c6a6a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/DevopsAPIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/java/org/wso2/carbon/apimgt/rest/api/devops/DevopsAPIUtils.java @@ -58,6 +58,8 @@ public static LoggingApiOutputListDTO getLoggingAPIList(List apiL loggingApiOutputDTO.setContext(apiLogInfoDTO.getContext()); loggingApiOutputDTO.setLogLevel(apiLogInfoDTO.getLogLevel()); loggingApiOutputDTO.setApiId(apiLogInfoDTO.getApiId()); + loggingApiOutputDTO.setResourceMethod(apiLogInfoDTO.getResourceMethod()); + loggingApiOutputDTO.setResourcePath(apiLogInfoDTO.getResourcePath()); loggingApiOutputDTOList.add(loggingApiOutputDTO); } loggingApiOutputListDTO.apis(loggingApiOutputDTOList); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml index 33e744c0768f..ca12c65a877f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/main/resources/devops-api.yaml @@ -248,6 +248,10 @@ components: example: /v1.0.0/pizza LoggingApiOutput: title: API Info object with log details + required: + - context + - logLevel + - apiId properties: context: type: string @@ -258,6 +262,12 @@ components: apiId: type: string example: 12d6e73c-778d-45ac-b57d-117c6c5092a4 + resourceMethod: + type: string + example: GET + resourcePath: + type: string + example: /v1.0.0/pizza Error: title: Error object returned with 4XX HTTP Status required: From 2fadd3d9875f67d1c3adf496acb92260ebbc2d15 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 27 Mar 2023 09:36:16 +0530 Subject: [PATCH 05/38] Unit test testGetApiLogging testcase failure fixed. --- .../java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index e677bfed5337..cdfbca9af0d1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -230,7 +230,10 @@ public List retrieveAPILoggerByAPIID(String tenant, String apiId) } catch (SQLException e) { handleException("Failed to retrieve organization", e); } - String apiLogLevel = apiLogInfoApiDTOList.get(0).getLogLevel(); + String apiLogLevel = null; + if (!apiLogInfoApiDTOList.isEmpty()) { + apiLogLevel = apiLogInfoApiDTOList.get(0).getLogLevel(); + } boolean isResourceLevelHasHighPriority = false; for (APILogInfoDTO apiLogInfoDTO : apiLogInfoApiResourceDTOList) { switch (apiLogInfoDTO.getLogLevel()) { From d3f2e0b089752ac78c0467f2876a5fac03498d9a Mon Sep 17 00:00:00 2001 From: shnrndk Date: Thu, 30 Mar 2023 10:22:53 +0530 Subject: [PATCH 06/38] /api-logging-configs GET rest api changed to support the resourceMethod and resourcePath properties. --- .../apimgt/gateway/handlers/LogsHandler.java | 8 ++++--- .../carbon/apimgt/impl/dao/LoggingMgtDAO.java | 21 +++++++++++++++++-- .../impl/dao/constants/SQLConstants.java | 2 +- .../impl/ApiLoggingConfigsApiServiceImpl.java | 2 ++ .../src/main/resources/api.yaml | 9 ++++++++ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index 21b46aeb7502..17413e46b32e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -54,6 +54,8 @@ public class LogsHandler extends AbstractSynapseHandler { private static final String UUID_HEADER = "UUID_HEADER"; private static final String CORRELATION_ID_HEADER = "CORRELATION_ID_HEADER"; protected static final String LOG_LEVEL = "LOG_LEVEL"; + protected static final String RESOURCE_PATH = "RESOURCE_PATH"; + protected static final String RESOURCE_METHOD = "RESOURCE_METHOD"; private static final String REQUEST_BODY_SIZE_ERROR = "Error occurred while building the message to calculate" + " the response body size"; @@ -278,7 +280,7 @@ private long buildResponseMessage(org.apache.synapse.MessageContext messageConte * * @param map Map containing API context and logLevel */ - public static Map syncAPILogData(Map map) { + public static Map syncAPILogData(Map map) { String apictx = (String) map.get("context"); String logLevel = (String) map.get("value"); log.debug("Log level for " + apictx + " is changed to " + logLevel); @@ -288,7 +290,7 @@ public static String getLogData(String context) { return APILoggerManager.getInstance().getPerAPILoggerList().get(context); } - public static Map getLogData() { + public static Map getLogData() { return APILoggerManager.getInstance().getPerAPILoggerList(); } @@ -299,7 +301,7 @@ public static Map getLogData() { * @return log level of the API or null if not */ private String getAPILogLevel(MessageContext ctx) { - Map logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); + Map logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); // if the logging API data holder is empty or null return null if (!logProperties.isEmpty()) { return LogUtils.getMatchingLogLevel(ctx, logProperties); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index cdfbca9af0d1..b2b54dd975d2 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -168,9 +168,10 @@ public List retrieveAPILoggerList(String organization, String log public List retrieveAllAPILoggerList() throws APIManagementException { List apiLogInfoDTOList = new ArrayList<>(); - String query = SQLConstants.RETRIEVE_ALL_PER_API_LOGGING_SQL; + String queryPerApi = SQLConstants.RETRIEVE_ALL_PER_API_LOGGING_SQL; + String queryPerApiResource = SQLConstants.RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL; try (Connection connection = APIMgtDBUtil.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement(query)) { + PreparedStatement preparedStatement = connection.prepareStatement(queryPerApi)) { try (ResultSet resultSet = preparedStatement.executeQuery()) { while (resultSet.next()) { String logLevel = APIConstants.LOG_LEVEL_OFF; @@ -182,6 +183,22 @@ public List retrieveAllAPILoggerList() throws APIManagementExcept apiLogInfoDTOList.add(apiLogInfoDTO); } } + PreparedStatement preparedStatementResource = connection.prepareStatement(queryPerApiResource); + { + try (ResultSet resultSet = preparedStatementResource.executeQuery()) { + while (resultSet.next()) { + String logLevel = APIConstants.LOG_LEVEL_OFF; + if (resultSet.getString(APIConstants.LOG_LEVEL) != null) { + logLevel = resultSet.getString(APIConstants.LOG_LEVEL); + } + APILogInfoDTO apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), + resultSet.getString(CONTEXT), logLevel, + resultSet.getString(APIConstants.RESOURCE_METHOD), + resultSet.getString(APIConstants.RESOURCE_PATH)); + apiLogInfoDTOList.add(apiLogInfoDTO); + } + } + } } catch (SQLException e) { handleException("Failed to retrieve organization", 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 49f0b6be6a24..9b3bf0f2f7ed 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 @@ -3038,7 +3038,7 @@ public class SQLConstants { "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF'"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_PER_API_LOGGING_ALL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.ORGANIZATION=?"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/java/org/wso2/carbon/apimgt/internal/service/impl/ApiLoggingConfigsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/java/org/wso2/carbon/apimgt/internal/service/impl/ApiLoggingConfigsApiServiceImpl.java index b7d7156875f2..ec93c2f62eeb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/java/org/wso2/carbon/apimgt/internal/service/impl/ApiLoggingConfigsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/java/org/wso2/carbon/apimgt/internal/service/impl/ApiLoggingConfigsApiServiceImpl.java @@ -56,6 +56,8 @@ public Response apiLoggingConfigsGet(MessageContext messageContext) { APILoggingConfigDTO apiLoggingConfigDTO = new APILoggingConfigDTO(); apiLoggingConfigDTO.setContext(apiLogInfo.getContext()); apiLoggingConfigDTO.setLogLevel(apiLogInfo.getLogLevel()); + apiLoggingConfigDTO.setResourceMethod(apiLogInfo.getResourceMethod()); + apiLoggingConfigDTO.setResourcePath(apiLogInfo.getResourcePath()); loggingAPIDTOList.add(apiLoggingConfigDTO); } } catch (APIManagementException e) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/resources/api.yaml b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/resources/api.yaml index e40c00fd75e8..b45e7feee77d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/resources/api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/main/resources/api.yaml @@ -1498,6 +1498,9 @@ definitions: $ref: '#/definitions/APILoggingConfig' APILoggingConfig: title: API Info object with log details + required: + - context + - logLevel properties: context: type: string @@ -1505,6 +1508,12 @@ definitions: logLevel: type: string example: all + resourceMethod: + type: string + example: GET + resourcePath: + type: string + example: /v1.0.0/pizza #----------------------------------------------------- # Correlation Configs Components List From 2c446ab5d31cb13b4cae5e42210039f77fc3e83c Mon Sep 17 00:00:00 2001 From: shnrndk Date: Thu, 30 Mar 2023 10:25:31 +0530 Subject: [PATCH 07/38] getAPILogLevel() method changed to compare the log level from api level and resource level. --- .../apimgt/gateway/APILoggerManager.java | 38 ++++++++-- .../apimgt/gateway/handlers/LogUtils.java | 70 +++++++++++++++++-- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java index 5d6ba4cda400..79750bd21638 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java @@ -46,7 +46,7 @@ */ public class APILoggerManager { private static final Log log = LogFactory.getLog(APILoggerManager.class); - private static final Map logProperties = new HashMap<>(); + private static final Map logProperties = new HashMap<>(); private static final APILoggerManager apiLoggerManager = new APILoggerManager(); private final EventHubConfigurationDto eventHubConfigurationDto; public static final int RETRIEVAL_RETRIES = 15; @@ -61,7 +61,17 @@ public void initializeAPILoggerList() { JSONArray apiLogArray = responseJson.getJSONArray("apis"); for (int i = 0; i < apiLogArray.length(); i++) { JSONObject apiLoggerObject = apiLogArray.getJSONObject(i); - logProperties.put(apiLoggerObject.getString("context"), apiLoggerObject.getString("logLevel")); + String resourceMethod = null; + String resourcePath = null; + if(!apiLoggerObject.isNull("resourceMethod") && !apiLoggerObject.isNull("resourcePath") ){ + resourceMethod = apiLoggerObject.getString("resourceMethod"); + resourcePath = apiLoggerObject.getString("resourcePath"); + } + logResourceProperties logResourceProperties = new logResourceProperties( + apiLoggerObject.getString("context"), + resourceMethod, + resourcePath); + logProperties.put(logResourceProperties, apiLoggerObject.getString("logLevel")); } if (log.isDebugEnabled()) { log.debug("Response : " + responseString); @@ -72,10 +82,11 @@ public void initializeAPILoggerList() { } public void updateLoggerMap(String apiContext, String logLevel) { - logProperties.put(apiContext, logLevel); + logResourceProperties logResourceProperties = new logResourceProperties(apiContext,null, null); + logProperties.put(logResourceProperties, logLevel); } - public Map getPerAPILoggerList() { + public Map getPerAPILoggerList() { return logProperties; } @@ -141,4 +152,23 @@ private String invokeService(String path, String tenantDomain) throws IOExceptio } return EntityUtils.toString(httpResponse.getEntity(), UTF8); } + + public class logResourceProperties { + private String resourceMethod = null; + private String resourcePath = null; + private String context = null; + + public logResourceProperties(String context, String resourceMethod, String resourcePath) { + this.context = context; + this.resourceMethod = resourceMethod; + this.resourcePath = resourcePath; + } + + public String getResourceMethod() { return resourceMethod; } + public void setResourceMethod(String resourceMethod) { this.resourceMethod = resourceMethod; } + public String getResourcePath() { return resourcePath; } + public void setResourcePath(String resourcePath) { this.resourcePath = resourcePath; } + public String getContext() { return context; } + public void setContext(String context) { this.context = context;} + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 6eb80621183d..d65e1e76b156 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -21,6 +21,7 @@ import org.apache.http.HttpHeaders; import org.apache.synapse.MessageContext; import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.wso2.carbon.apimgt.gateway.APILoggerManager; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.impl.APIConstants; @@ -119,14 +120,71 @@ protected static String getTransportInURL(org.apache.synapse.MessageContext mess return transportInURL.substring(1); } - protected static String getMatchingLogLevel(MessageContext ctx, Map logProperties) { + protected static String getHTTPMethod(org.apache.synapse.MessageContext messageContext) { + org.apache.axis2.context.MessageContext axis2MsgContext = ((Axis2MessageContext) messageContext) + .getAxis2MessageContext(); + String httpMethod = (String) axis2MsgContext.getProperty("HTTP_METHOD"); + return httpMethod; + } + + protected static String getMatchingLogLevel(MessageContext ctx, + Map logProperties) { + String apiCtx = LogUtils.getTransportInURL(ctx); - for (Map.Entry entry : logProperties.entrySet()) { - String key = entry.getKey().substring(1); - if (apiCtx.startsWith(key + "/") || apiCtx.equals(key)) { - ctx.setProperty(LogsHandler.LOG_LEVEL, entry.getValue()); + String apiHttpMethod = LogUtils.getHTTPMethod(ctx); + String apiLogLevel = null; + String resourceLogLevel = null; + String resourcePath = null; + String resourceMethod = null; + for (Map.Entry entry : logProperties.entrySet()) { + APILoggerManager.logResourceProperties key = entry.getKey(); + key.getResourceMethod(); + String apiResourcePath = apiCtx.split("/", 3)[2]; + if (("/" + apiResourcePath).equals(key.getResourcePath()) && apiHttpMethod.equals(key.getResourceMethod())) { + if (key.getContext().startsWith(key.getContext() + "/") || key.getContext().equals(key.getContext())) { + resourceLogLevel = entry.getValue(); + resourcePath = key.getResourcePath(); + resourceMethod = key.getResourceMethod(); + } + } else if (key.getResourcePath() == null && key.getResourceMethod() == null) { + if (key.getContext().startsWith(key.getContext() + "/") || key.getContext().equals(key.getContext())) { + apiLogLevel = entry.getValue(); + } + } + } + boolean isResourceLevelHasHighPriority = false; + if (apiLogLevel != null || resourceLogLevel != null) { + switch (resourceLogLevel) { + case APIConstants.LOG_LEVEL_FULL: + isResourceLevelHasHighPriority = true; + break; + case APIConstants.LOG_LEVEL_STANDARD: + if (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) + || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + isResourceLevelHasHighPriority = true; + break; + } else { + break; + } + case APIConstants.LOG_LEVEL_BASIC: + if (apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + isResourceLevelHasHighPriority = true; + } else { + break; + } + case APIConstants.LOG_LEVEL_OFF: + break; + } + if (isResourceLevelHasHighPriority) { + ctx.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); + ctx.setProperty(LogsHandler.RESOURCE_PATH, resourcePath); + ctx.setProperty(LogsHandler.RESOURCE_METHOD, resourceMethod); + ctx.setProperty("API_TO", apiCtx); + return resourceLogLevel; + } else { + ctx.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); ctx.setProperty("API_TO", apiCtx); - return entry.getValue(); + return apiLogLevel; } } return null; From 7eb9ec2265a635c77c045f9696b6b45c05d25815 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 3 Apr 2023 08:57:51 +0530 Subject: [PATCH 08/38] logResourceProperties inner class changed to properties hash map. --- .../apimgt/gateway/APILoggerManager.java | 40 ++++++------------- .../apimgt/gateway/handlers/LogUtils.java | 23 +++++------ .../apimgt/gateway/handlers/LogsHandler.java | 6 +-- 3 files changed, 25 insertions(+), 44 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java index 79750bd21638..c34cf47042a7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java @@ -46,7 +46,7 @@ */ public class APILoggerManager { private static final Log log = LogFactory.getLog(APILoggerManager.class); - private static final Map logProperties = new HashMap<>(); + private Map, String> logProperties = new HashMap<>(); private static final APILoggerManager apiLoggerManager = new APILoggerManager(); private final EventHubConfigurationDto eventHubConfigurationDto; public static final int RETRIEVAL_RETRIES = 15; @@ -67,11 +67,11 @@ public void initializeAPILoggerList() { resourceMethod = apiLoggerObject.getString("resourceMethod"); resourcePath = apiLoggerObject.getString("resourcePath"); } - logResourceProperties logResourceProperties = new logResourceProperties( - apiLoggerObject.getString("context"), - resourceMethod, - resourcePath); - logProperties.put(logResourceProperties, apiLoggerObject.getString("logLevel")); + Map properties = new HashMap<>(); + properties.put("context", apiLoggerObject.getString("context")); + properties.put("resourceMethod", resourceMethod); + properties.put("resourcePath", resourcePath); + logProperties.put(properties, apiLoggerObject.getString("logLevel")); } if (log.isDebugEnabled()) { log.debug("Response : " + responseString); @@ -82,11 +82,14 @@ public void initializeAPILoggerList() { } public void updateLoggerMap(String apiContext, String logLevel) { - logResourceProperties logResourceProperties = new logResourceProperties(apiContext,null, null); - logProperties.put(logResourceProperties, logLevel); + Map properties = new HashMap<>(); + properties.put("context", apiContext); + properties.put("resourcePath", null); + properties.put("resourceMethod", null); + logProperties.put(properties, logLevel); } - public Map getPerAPILoggerList() { + public Map, String> getPerAPILoggerList() { return logProperties; } @@ -152,23 +155,4 @@ private String invokeService(String path, String tenantDomain) throws IOExceptio } return EntityUtils.toString(httpResponse.getEntity(), UTF8); } - - public class logResourceProperties { - private String resourceMethod = null; - private String resourcePath = null; - private String context = null; - - public logResourceProperties(String context, String resourceMethod, String resourcePath) { - this.context = context; - this.resourceMethod = resourceMethod; - this.resourcePath = resourcePath; - } - - public String getResourceMethod() { return resourceMethod; } - public void setResourceMethod(String resourceMethod) { this.resourceMethod = resourceMethod; } - public String getResourcePath() { return resourcePath; } - public void setResourcePath(String resourcePath) { this.resourcePath = resourcePath; } - public String getContext() { return context; } - public void setContext(String context) { this.context = context;} - } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index d65e1e76b156..ec98e1f459a7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -21,7 +21,6 @@ import org.apache.http.HttpHeaders; import org.apache.synapse.MessageContext; import org.apache.synapse.core.axis2.Axis2MessageContext; -import org.wso2.carbon.apimgt.gateway.APILoggerManager; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.impl.APIConstants; @@ -128,26 +127,24 @@ protected static String getHTTPMethod(org.apache.synapse.MessageContext messageC } protected static String getMatchingLogLevel(MessageContext ctx, - Map logProperties) { - + Map, String> logProperties) { String apiCtx = LogUtils.getTransportInURL(ctx); String apiHttpMethod = LogUtils.getHTTPMethod(ctx); String apiLogLevel = null; String resourceLogLevel = null; String resourcePath = null; String resourceMethod = null; - for (Map.Entry entry : logProperties.entrySet()) { - APILoggerManager.logResourceProperties key = entry.getKey(); - key.getResourceMethod(); + for (Map.Entry, String> entry : logProperties.entrySet()) { + Map key = entry.getKey(); String apiResourcePath = apiCtx.split("/", 3)[2]; - if (("/" + apiResourcePath).equals(key.getResourcePath()) && apiHttpMethod.equals(key.getResourceMethod())) { - if (key.getContext().startsWith(key.getContext() + "/") || key.getContext().equals(key.getContext())) { + if (("/" + apiResourcePath).equals(key.get("resourcePath")) && apiHttpMethod.equals(key.get("resourceMethod"))) { + if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { resourceLogLevel = entry.getValue(); - resourcePath = key.getResourcePath(); - resourceMethod = key.getResourceMethod(); + resourcePath = key.get("resourcePath"); + resourceMethod = key.get("resourceMethod"); } - } else if (key.getResourcePath() == null && key.getResourceMethod() == null) { - if (key.getContext().startsWith(key.getContext() + "/") || key.getContext().equals(key.getContext())) { + } else if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { + if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { apiLogLevel = entry.getValue(); } } @@ -182,7 +179,7 @@ protected static String getMatchingLogLevel(MessageContext ctx, ctx.setProperty("API_TO", apiCtx); return resourceLogLevel; } else { - ctx.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); + ctx.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); ctx.setProperty("API_TO", apiCtx); return apiLogLevel; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index 17413e46b32e..ef2c97419fdb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -280,7 +280,7 @@ private long buildResponseMessage(org.apache.synapse.MessageContext messageConte * * @param map Map containing API context and logLevel */ - public static Map syncAPILogData(Map map) { + public static Map, String> syncAPILogData(Map map) { String apictx = (String) map.get("context"); String logLevel = (String) map.get("value"); log.debug("Log level for " + apictx + " is changed to " + logLevel); @@ -290,7 +290,7 @@ public static String getLogData(String context) { return APILoggerManager.getInstance().getPerAPILoggerList().get(context); } - public static Map getLogData() { + public static Map, String> getLogData() { return APILoggerManager.getInstance().getPerAPILoggerList(); } @@ -301,7 +301,7 @@ public static Map getLogData() { * @return log level of the API or null if not */ private String getAPILogLevel(MessageContext ctx) { - Map logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); + Map, String> logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); // if the logging API data holder is empty or null return null if (!logProperties.isEmpty()) { return LogUtils.getMatchingLogLevel(ctx, logProperties); From b71e155fe18c327037221dd53c9d6639c8c9a6a3 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 3 Apr 2023 08:58:50 +0530 Subject: [PATCH 09/38] Changed RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL sql query to return non revision apis only. --- .../org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9b3bf0f2f7ed..07b56bcb8983 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 @@ -3038,7 +3038,7 @@ public class SQLConstants { "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF'"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF' AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_ALL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.ORGANIZATION=?"; From a29e40d07399387caad046cbde73d76889c2a07d Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 3 Apr 2023 17:32:53 +0530 Subject: [PATCH 10/38] resourceMethod and resourcePath added APIEvent class --- .../carbon/apimgt/gateway/APILoggerManager.java | 6 +++--- .../listeners/GatewayJMSMessageListener.java | 3 ++- .../apimgt/impl/notifier/events/APIEvent.java | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java index c34cf47042a7..69de6600424d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java @@ -81,11 +81,11 @@ public void initializeAPILoggerList() { } } - public void updateLoggerMap(String apiContext, String logLevel) { + public void updateLoggerMap(String apiContext, String logLevel, String resourceMethod, String resourcePath) { Map properties = new HashMap<>(); properties.put("context", apiContext); - properties.put("resourcePath", null); - properties.put("resourceMethod", null); + properties.put("resourcePath", resourceMethod); + properties.put("resourceMethod", resourcePath); logProperties.put(properties, logLevel); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java index 97ecb3ad8d8d..18f1d34c5a3c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java @@ -324,7 +324,8 @@ public void run() { } } else if (EventType.UDATE_API_LOG_LEVEL.toString().equals(eventType)) { APIEvent apiEvent = new Gson().fromJson(eventJson, APIEvent.class); - APILoggerManager.getInstance().updateLoggerMap(apiEvent.getApiContext(), apiEvent.getLogLevel()); + APILoggerManager.getInstance().updateLoggerMap(apiEvent.getApiContext(), apiEvent.getLogLevel(), + apiEvent.getResourceMethod(), apiEvent.getResourcePath()); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java index 505acb35fe26..4023b1541dd7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java @@ -36,13 +36,18 @@ public class APIEvent extends Event { private String apiType; private String apiStatus; private String logLevel; + private String resourceMethod; + private String resourcePath; private APIConstants.EventAction action; - public APIEvent(String uuid, String logLevel, String type, String apiContext) { + public APIEvent(String uuid, String logLevel, String type, String apiContext, + String resourceMethod, String resourcePath, String tenantId) { this.uuid = uuid; this.logLevel = logLevel; this.type = type; this.apiContext = apiContext; + this.resourceMethod = resourceMethod; + this.resourcePath = resourcePath; } public APIEvent(String uuid, String apiName, String apiVersion, String apiProvider, String apiType, @@ -215,6 +220,14 @@ public String getLogLevel() { return logLevel; } + public String getResourceMethod() { + return resourceMethod; + } + + public String getResourcePath() { + return resourcePath; + } + public APIConstants.EventAction getAction() { return action; } From 2529c776c49287fdd6893bed4def99e90040b343 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 3 Apr 2023 17:32:53 +0530 Subject: [PATCH 11/38] resourceMethod and resourcePath added APIEvent class --- .../devops/impl/logging/APILoggingImpl.java | 6 +++--- .../carbon/apimgt/gateway/APILoggerManager.java | 6 +++--- .../listeners/GatewayJMSMessageListener.java | 3 ++- .../apimgt/impl/notifier/events/APIEvent.java | 15 ++++++++++++++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java index 49aaa17a034e..0f95cf76d764 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java @@ -62,12 +62,12 @@ public void addUpdateAPILogger(String tenantId, String apiId, String logLevel, S ExceptionCodes.from(ExceptionCodes.LOGGING_API_MISSING_DATA)); } - publishLogAPIData(tenantId, apiId, logLevel); + publishLogAPIData(tenantId, apiId, logLevel, resourceMethod, resourcePath); } - private void publishLogAPIData(String tenantId, String apiId, String logLevel) throws APIManagementException { + private void publishLogAPIData(String tenantId, String apiId, String logLevel, String resourceMethod, String resourcePath) throws APIManagementException { APIEvent apiEvent = new APIEvent(apiId, logLevel, APIConstants.EventType.UDATE_API_LOG_LEVEL.name(), - apiMgtDAO.getAPIContext(apiId)); + apiMgtDAO.getAPIContext(apiId), resourceMethod, resourcePath, tenantId); APIUtil.sendNotification(apiEvent, APIConstants.NotifierType.API.name()); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java index c34cf47042a7..69de6600424d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java @@ -81,11 +81,11 @@ public void initializeAPILoggerList() { } } - public void updateLoggerMap(String apiContext, String logLevel) { + public void updateLoggerMap(String apiContext, String logLevel, String resourceMethod, String resourcePath) { Map properties = new HashMap<>(); properties.put("context", apiContext); - properties.put("resourcePath", null); - properties.put("resourceMethod", null); + properties.put("resourcePath", resourceMethod); + properties.put("resourceMethod", resourcePath); logProperties.put(properties, logLevel); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java index 97ecb3ad8d8d..18f1d34c5a3c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/listeners/GatewayJMSMessageListener.java @@ -324,7 +324,8 @@ public void run() { } } else if (EventType.UDATE_API_LOG_LEVEL.toString().equals(eventType)) { APIEvent apiEvent = new Gson().fromJson(eventJson, APIEvent.class); - APILoggerManager.getInstance().updateLoggerMap(apiEvent.getApiContext(), apiEvent.getLogLevel()); + APILoggerManager.getInstance().updateLoggerMap(apiEvent.getApiContext(), apiEvent.getLogLevel(), + apiEvent.getResourceMethod(), apiEvent.getResourcePath()); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java index 505acb35fe26..4023b1541dd7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/notifier/events/APIEvent.java @@ -36,13 +36,18 @@ public class APIEvent extends Event { private String apiType; private String apiStatus; private String logLevel; + private String resourceMethod; + private String resourcePath; private APIConstants.EventAction action; - public APIEvent(String uuid, String logLevel, String type, String apiContext) { + public APIEvent(String uuid, String logLevel, String type, String apiContext, + String resourceMethod, String resourcePath, String tenantId) { this.uuid = uuid; this.logLevel = logLevel; this.type = type; this.apiContext = apiContext; + this.resourceMethod = resourceMethod; + this.resourcePath = resourcePath; } public APIEvent(String uuid, String apiName, String apiVersion, String apiProvider, String apiType, @@ -215,6 +220,14 @@ public String getLogLevel() { return logLevel; } + public String getResourceMethod() { + return resourceMethod; + } + + public String getResourcePath() { + return resourcePath; + } + public APIConstants.EventAction getAction() { return action; } From dacb9ddc77bc9ac8a8423e7ee062f5aafb8b7e30 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 5 Apr 2023 08:16:14 +0530 Subject: [PATCH 12/38] Fixed some bugs in the logic. --- .../apimgt/gateway/handlers/LogUtils.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index ec98e1f459a7..0b07eee7975e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -150,29 +150,26 @@ protected static String getMatchingLogLevel(MessageContext ctx, } } boolean isResourceLevelHasHighPriority = false; - if (apiLogLevel != null || resourceLogLevel != null) { + if (resourceLogLevel != null) { switch (resourceLogLevel) { case APIConstants.LOG_LEVEL_FULL: isResourceLevelHasHighPriority = true; break; case APIConstants.LOG_LEVEL_STANDARD: - if (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) - || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + if (apiLogLevel != null && apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC)) { isResourceLevelHasHighPriority = true; break; } else { break; } case APIConstants.LOG_LEVEL_BASIC: - if (apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + if (apiLogLevel == null) { isResourceLevelHasHighPriority = true; } else { break; } - case APIConstants.LOG_LEVEL_OFF: - break; } - if (isResourceLevelHasHighPriority) { + if (isResourceLevelHasHighPriority || apiLogLevel == null) { ctx.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); ctx.setProperty(LogsHandler.RESOURCE_PATH, resourcePath); ctx.setProperty(LogsHandler.RESOURCE_METHOD, resourceMethod); @@ -183,7 +180,12 @@ protected static String getMatchingLogLevel(MessageContext ctx, ctx.setProperty("API_TO", apiCtx); return apiLogLevel; } + } else if (apiLogLevel != null) { + ctx.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); + ctx.setProperty("API_TO", apiCtx); + return apiLogLevel; + } else { + return null; } - return null; } } \ No newline at end of file From 557a1d5062976b907ca3fa3bc979259c8d1287cc Mon Sep 17 00:00:00 2001 From: shnrndk Date: Fri, 7 Apr 2023 07:59:56 +0530 Subject: [PATCH 13/38] Log properties multiple key adding bug fixed --- .../java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java index 69de6600424d..91e6e93a8e5a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/APILoggerManager.java @@ -84,8 +84,8 @@ public void initializeAPILoggerList() { public void updateLoggerMap(String apiContext, String logLevel, String resourceMethod, String resourcePath) { Map properties = new HashMap<>(); properties.put("context", apiContext); - properties.put("resourcePath", resourceMethod); - properties.put("resourceMethod", resourcePath); + properties.put("resourcePath", resourcePath); + properties.put("resourceMethod", resourceMethod); logProperties.put(properties, logLevel); } From 391d5eab51736fa0e777838b9c7a3b6b754bf90e Mon Sep 17 00:00:00 2001 From: shnrndk Date: Sat, 8 Apr 2023 14:54:29 +0530 Subject: [PATCH 14/38] regex matching added to resource path checking --- .../carbon/apimgt/gateway/handlers/LogUtils.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 0b07eee7975e..8771b90b1642 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -137,14 +137,20 @@ protected static String getMatchingLogLevel(MessageContext ctx, for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); String apiResourcePath = apiCtx.split("/", 3)[2]; - if (("/" + apiResourcePath).equals(key.get("resourcePath")) && apiHttpMethod.equals(key.get("resourceMethod"))) { - if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { + String logResourcePath = key.get("resourcePath"); + String resourcePathRegexPattern = logResourcePath.replace("/","\\/"); + resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}","\\\\d+"); + if(("/"+apiResourcePath).matches(resourcePathRegexPattern) + && apiHttpMethod.equals(key.get("resourceMethod"))){ + if (key.get("context").startsWith(key.get("context") + "/") || + key.get("context").equals(key.get("context"))) { resourceLogLevel = entry.getValue(); resourcePath = key.get("resourcePath"); resourceMethod = key.get("resourceMethod"); } } else if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { + if (key.get("context").startsWith(key.get("context") + "/") || + key.get("context").equals(key.get("context"))) { apiLogLevel = entry.getValue(); } } From 5f63a96b09fa59b9a181f45bcb7b39e814587e61 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Sat, 8 Apr 2023 15:33:37 +0530 Subject: [PATCH 15/38] Code reformatted --- .../org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 8771b90b1642..28e4504d2160 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -138,10 +138,10 @@ protected static String getMatchingLogLevel(MessageContext ctx, Map key = entry.getKey(); String apiResourcePath = apiCtx.split("/", 3)[2]; String logResourcePath = key.get("resourcePath"); - String resourcePathRegexPattern = logResourcePath.replace("/","\\/"); - resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}","\\\\d+"); - if(("/"+apiResourcePath).matches(resourcePathRegexPattern) - && apiHttpMethod.equals(key.get("resourceMethod"))){ + String resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); + resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", "\\\\d+"); + if (("/" + apiResourcePath).matches(resourcePathRegexPattern) + && apiHttpMethod.equals(key.get("resourceMethod"))) { if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { resourceLogLevel = entry.getValue(); From 93ac087d155cb5a2a6827c9213db7b3e4acf4473 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 11 Apr 2023 17:06:58 +0530 Subject: [PATCH 16/38] Added validation to check api resource is valid or not when adding the resource log level --- .../carbon/apimgt/api/ExceptionCodes.java | 1 + .../devops/impl/logging/APILoggingImpl.java | 16 +++++++--- .../carbon/apimgt/impl/dao/LoggingMgtDAO.java | 30 +++++++++++++++++++ .../impl/dao/constants/SQLConstants.java | 2 ++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java index 2c482586704a..20b45fbc97fa 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java @@ -494,6 +494,7 @@ public enum ExceptionCodes implements ErrorHandler { LOGGING_API_NOT_FOUND(901400, "Requested Resource Not Found", 404, "Request API Not Found for context: %s"), LOGGING_API_INCORRECT_LOG_LEVEL(901401, "Bad Request", 400, "Log level should be either OFF, BASIC, STANDARD or FULL"), LOGGING_API_MISSING_DATA(901402, "Missing data", 400, "API context or log level is missing"), + LOGGING_API_RESOURCE_NOT_FOUND(901403, "Requested Resource Not Found", 400, "Requested API Resource Not Found"), CORRELATION_CONFIG_BAD_REQUEST(902020, "Bad Request", 400, "Request body can not have empty elements"), CORRELATION_CONFIG_BAD_REQUEST_INVALID_NAME(902021, "Bad Request", 400, "Request body contains invalid correlation component name"), //Service Catalog related error codes diff --git a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java index 0f95cf76d764..12360fd98237 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java @@ -38,7 +38,9 @@ public class APILoggingImpl { private static final String PER_API_LOGGING_PERMISSION_PATH = "/permission/protected/configure/logging"; private static final String INVALID_LOGGING_PERMISSION = "Invalid logging permission"; - private static final String INCORRECT_LOGGING_PER_API_RESOURCE_REQUEST = "Resource Method and Resource Path both should included"; + private static final String INCORRECT_LOGGING_PER_API_RESOURCE_REQUEST = "Resource Method and Resource Path both " + + "should included"; + private static final String REQUIRED_API_RESOURCE_IS_NOT_AVAILABLE = "Requested resource is not available"; private final ApiMgtDAO apiMgtDAO = ApiMgtDAO.getInstance(); public void addUpdateAPILogger(String tenantId, String apiId, String logLevel, String resourceMethod, @@ -51,10 +53,16 @@ public void addUpdateAPILogger(String tenantId, String apiId, String logLevel, S throw new APIManagementException(INVALID_LOGGING_PERMISSION, ExceptionCodes.from(ExceptionCodes.INVALID_PERMISSION)); } - + boolean isAPIResourceExists = LoggingMgtDAO.getInstance().checkAPILoggerPerResourceAvailable(tenantId, apiId, + resourceMethod.toUpperCase(), resourcePath); if (resourceMethod != null && resourcePath != null) { - LoggingMgtDAO.getInstance().addAPILoggerPerResource(tenantId, apiId, logLevel, resourceMethod.toUpperCase(), - resourcePath); + if (isAPIResourceExists) { + LoggingMgtDAO.getInstance().addAPILoggerPerResource(tenantId, apiId, logLevel, + resourceMethod.toUpperCase(), resourcePath); + } else { + throw new APIManagementException(REQUIRED_API_RESOURCE_IS_NOT_AVAILABLE, + ExceptionCodes.from(ExceptionCodes.LOGGING_API_RESOURCE_NOT_FOUND)); + } } else if (resourceMethod == null && resourcePath == null) { LoggingMgtDAO.getInstance().addAPILogger(tenantId, apiId, logLevel); } else { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index b2b54dd975d2..faa3c7ce87af 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -99,6 +99,36 @@ public void addAPILoggerPerResource(String organization, String apiId, String lo } } + public boolean checkAPILoggerPerResourceAvailable(String organization, String apiId, String resourceMethod, + String resourcePath) throws APIManagementException { + boolean isAPILoggerPerResourceAvailable = false; + try (Connection addLoggingCon = APIMgtDBUtil.getConnection()) { + try (PreparedStatement preparedStatement = addLoggingCon.prepareStatement( + SQLConstants.CHECK_PER_API_RESOURCE_IS_AVAILABLE_LOGGING_SQL)) { + preparedStatement.setString(1, apiId); + preparedStatement.setString(2, organization); + preparedStatement.setString(3, resourceMethod); + preparedStatement.setString(4, resourcePath); + try (ResultSet resultSet = preparedStatement.executeQuery()) { + while (resultSet.next()) { + if (resultSet.getString(APIConstants.LOG_LEVEL) != null) { + isAPILoggerPerResourceAvailable = true; + } + } + } + } catch (SQLException e) { + throw new ApiLoggingMgtException("Error while checking resource API logger", e); + } + } catch (SQLException e) { + handleException("Failed to check the resource is available for " + apiId, e); + } + if (isAPILoggerPerResourceAvailable) { + return true; + } else { + return false; + } + } + public List retrieveAPILoggerList(String organization, String logLevel) throws APIManagementException { List apiLogInfoDTOList = new ArrayList<>(); 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 07b56bcb8983..26b1907edac0 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 @@ -3014,6 +3014,8 @@ public class SQLConstants { "UPDATE AM_API SET LOG_LEVEL=? WHERE API_UUID=? AND ORGANIZATION=?"; public static final String ADD_PER_API_RESOURCE_LOGGING_SQL = "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; + public static final String CHECK_PER_API_RESOURCE_IS_AVAILABLE_LOGGING_SQL = + "SELECT * FROM AM_API_URL_MAPPING WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; public static final String RETRIEVE_PER_API_LOGGING_OFF_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION=?"; From 24ade92fa859b4c013ed73677cb7851f33a09a19 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 12 Apr 2023 10:28:18 +0530 Subject: [PATCH 17/38] If condition logic simplified --- .../carbon/apimgt/gateway/handlers/LogUtils.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 28e4504d2160..eaa38568c100 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -140,17 +140,14 @@ protected static String getMatchingLogLevel(MessageContext ctx, String logResourcePath = key.get("resourcePath"); String resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", "\\\\d+"); - if (("/" + apiResourcePath).matches(resourcePathRegexPattern) - && apiHttpMethod.equals(key.get("resourceMethod"))) { - if (key.get("context").startsWith(key.get("context") + "/") || - key.get("context").equals(key.get("context"))) { + if (key.get("context").startsWith(key.get("context") + "/") || + key.get("context").equals(key.get("context"))) { + if (("/" + apiResourcePath).matches(resourcePathRegexPattern) + && apiHttpMethod.equals(key.get("resourceMethod"))) { resourceLogLevel = entry.getValue(); resourcePath = key.get("resourcePath"); resourceMethod = key.get("resourceMethod"); - } - } else if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - if (key.get("context").startsWith(key.get("context") + "/") || - key.get("context").equals(key.get("context"))) { + } else if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { apiLogLevel = entry.getValue(); } } From 8e7f1972659a5e30c64fcd127998c55bb86fc35e Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 12 Apr 2023 11:00:13 +0530 Subject: [PATCH 18/38] NullPointerException fixed when passing without resourcePath and resourceMethod --- .../carbon/apimgt/devops/impl/logging/APILoggingImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java index 12360fd98237..0c7267351cbe 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.devops.impl/src/main/java/org/wso2/carbon/apimgt/devops/impl/logging/APILoggingImpl.java @@ -53,9 +53,9 @@ public void addUpdateAPILogger(String tenantId, String apiId, String logLevel, S throw new APIManagementException(INVALID_LOGGING_PERMISSION, ExceptionCodes.from(ExceptionCodes.INVALID_PERMISSION)); } - boolean isAPIResourceExists = LoggingMgtDAO.getInstance().checkAPILoggerPerResourceAvailable(tenantId, apiId, - resourceMethod.toUpperCase(), resourcePath); if (resourceMethod != null && resourcePath != null) { + boolean isAPIResourceExists = LoggingMgtDAO.getInstance().checkAPILoggerPerResourceAvailable(tenantId, + apiId, resourceMethod.toUpperCase(), resourcePath); if (isAPIResourceExists) { LoggingMgtDAO.getInstance().addAPILoggerPerResource(tenantId, apiId, logLevel, resourceMethod.toUpperCase(), resourcePath); From 4f0eac8be1f11a4577e8375f076d3b6ce8d70a86 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 12 Apr 2023 11:56:02 +0530 Subject: [PATCH 19/38] Null pointer issue fixed when the resourcePath is null. --- .../carbon/apimgt/gateway/handlers/LogUtils.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index eaa38568c100..be909d1880e0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -134,21 +134,24 @@ protected static String getMatchingLogLevel(MessageContext ctx, String resourceLogLevel = null; String resourcePath = null; String resourceMethod = null; + String logResourcePath, resourcePathRegexPattern = null; for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); String apiResourcePath = apiCtx.split("/", 3)[2]; - String logResourcePath = key.get("resourcePath"); - String resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); - resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", "\\\\d+"); + if (key.containsKey("resourcePath") && key.get("resourcePath") != null) { + logResourcePath = key.get("resourcePath"); + resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); + resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", "\\\\d+"); + } if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { - if (("/" + apiResourcePath).matches(resourcePathRegexPattern) + if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { + apiLogLevel = entry.getValue(); + } else if (("/" + apiResourcePath).matches(resourcePathRegexPattern) && apiHttpMethod.equals(key.get("resourceMethod"))) { resourceLogLevel = entry.getValue(); resourcePath = key.get("resourcePath"); resourceMethod = key.get("resourceMethod"); - } else if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - apiLogLevel = entry.getValue(); } } } From ec5a893b75e6fb215ca7ec80c60a476c8c57ed9a Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 12 Apr 2023 14:37:07 +0530 Subject: [PATCH 20/38] resourcePath regex matching changed to support - and alphabets and not only digits. --- .../java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index be909d1880e0..df94fc9eb0bd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -141,7 +141,8 @@ protected static String getMatchingLogLevel(MessageContext ctx, if (key.containsKey("resourcePath") && key.get("resourcePath") != null) { logResourcePath = key.get("resourcePath"); resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); - resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", "\\\\d+"); + resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", + "\\\\w{1,}([-]?\\\\w{1,})+"); } if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { From 62c4bdc26390097e7f2a520f0bd3675ab83e6cf0 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 12 Apr 2023 18:15:49 +0530 Subject: [PATCH 21/38] added log level off comparison to the filter --- .../org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index df94fc9eb0bd..1fc041c1881a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -163,14 +163,15 @@ protected static String getMatchingLogLevel(MessageContext ctx, isResourceLevelHasHighPriority = true; break; case APIConstants.LOG_LEVEL_STANDARD: - if (apiLogLevel != null && apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC)) { + if (apiLogLevel != null && (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) || + apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF))) { isResourceLevelHasHighPriority = true; break; } else { break; } case APIConstants.LOG_LEVEL_BASIC: - if (apiLogLevel == null) { + if (apiLogLevel == null || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { isResourceLevelHasHighPriority = true; } else { break; From 44c75bfd0335b97ac86d18e692e67f5807eeef1b Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 17 Apr 2023 18:28:39 +0530 Subject: [PATCH 22/38] Regex pattern match updated --- .../java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 1fc041c1881a..a584547c4483 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -142,7 +142,7 @@ protected static String getMatchingLogLevel(MessageContext ctx, logResourcePath = key.get("resourcePath"); resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", - "\\\\w{1,}([-]?\\\\w{1,})+"); + "\\\\w{0,}([-,_]?\\\\w{1,})+"); } if (key.get("context").startsWith(key.get("context") + "/") || key.get("context").equals(key.get("context"))) { From 0eca0a37f67a665fd6a10ee54a8a9141d771c685 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 17 Apr 2023 19:23:05 +0530 Subject: [PATCH 23/38] Array index out of bound error fixed. --- .../org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index a584547c4483..02dd4f8e6801 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -137,7 +137,12 @@ protected static String getMatchingLogLevel(MessageContext ctx, String logResourcePath, resourcePathRegexPattern = null; for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); - String apiResourcePath = apiCtx.split("/", 3)[2]; + String apiResourcePath; + if (apiCtx.split("/", 3).length > 2) { + apiResourcePath = apiCtx.split("/", 3)[2]; + } else { + apiResourcePath = ""; + } if (key.containsKey("resourcePath") && key.get("resourcePath") != null) { logResourcePath = key.get("resourcePath"); resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); From 529c80650ec6f0a593b7a89b95477e1c032faaf5 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 18 Apr 2023 10:20:37 +0530 Subject: [PATCH 24/38] Get log details of all apis not returning resource methods and paths fixed. --- .../org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java | 4 +++- .../carbon/apimgt/impl/dao/constants/SQLConstants.java | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java index faa3c7ce87af..bc9774669393 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/LoggingMgtDAO.java @@ -185,7 +185,9 @@ public List retrieveAPILoggerList(String organization, String log retrievedLogLevel = resultSet.getString(APIConstants.LOG_LEVEL); } apiLogInfoDTO = new APILogInfoDTO(resultSet.getString(API_UUID), - resultSet.getString(CONTEXT), retrievedLogLevel); + resultSet.getString(CONTEXT), retrievedLogLevel, + resultSet.getString(APIConstants.RESOURCE_METHOD), + resultSet.getString(APIConstants.RESOURCE_PATH)); apiLogInfoDTOList.add(apiLogInfoDTO); } } 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 26b1907edac0..469761d24329 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 @@ -3020,22 +3020,22 @@ public class SQLConstants { "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_OFF_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BASIC_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_STANDARD_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_STANDARD_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_FULL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_FULL_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_ALL_PER_API_LOGGING_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; @@ -3045,7 +3045,7 @@ public class SQLConstants { "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_ALL_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BY_UUID_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.API_UUID = ? AND AM_API.ORGANIZATION=?"; From 6057715152f58430d758795102ccbd98fa4cd7fe Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:37:08 +0530 Subject: [PATCH 25/38] removing regex usage for finding the resource path used the implementation of URITemplateBasedDispatcher for resource matching issue: https://github.com/wso2/api-manager/issues/1564 (cherry picked from commit 5b3818c9f9d973df58a19f9614cfde3c9d36fa6a) --- .../apimgt/gateway/handlers/LogUtils.java | 86 ++++++++++++++++++- .../apimgt/gateway/handlers/LogsHandler.java | 2 + .../handlers/security/CORSRequestHandler.java | 18 +++- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 02dd4f8e6801..8bedc3a7692e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -18,13 +18,25 @@ package org.wso2.carbon.apimgt.gateway.handlers; +import org.apache.axis2.Constants; import org.apache.http.HttpHeaders; import org.apache.synapse.MessageContext; +import org.apache.synapse.api.API; +import org.apache.synapse.api.ApiUtils; +import org.apache.synapse.api.Resource; +import org.apache.synapse.api.dispatch.DispatcherHelper; +import org.apache.synapse.api.dispatch.RESTDispatcher; +import org.apache.synapse.api.dispatch.URITemplateBasedDispatcher; +import org.apache.synapse.api.dispatch.URITemplateHelper; +import org.apache.synapse.api.version.DefaultStrategy; +import org.apache.synapse.api.version.VersionStrategy; +import org.apache.synapse.config.xml.rest.VersionStrategyFactory; import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.rest.RESTConstants; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.impl.APIConstants; -import java.util.Map; +import java.util.*; /** * Provides util methods for the LogsHandler @@ -126,6 +138,78 @@ protected static String getHTTPMethod(org.apache.synapse.MessageContext messageC return httpMethod; } + protected static void fetchLogLevel(MessageContext messageContext, + Map, String> logProperties) { + Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); + List duplicateApiSet = new ArrayList(apiSet); + API selectedApi = null; + String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). + getProperty("TransportInURL").toString(); + for (API api : duplicateApiSet) { + if (apiContext.contains(api.getContext())) { + selectedApi = api; + //break; + } + } + String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext(). + getProperty(Constants.Configuration.HTTP_METHOD); + org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext) + .getAxis2MessageContext(); + Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); + String corsRequestMethod = (String) headers.get(APIConstants.CORSHeaders.ACCESS_CONTROL_REQUEST_METHOD); + if (selectedApi != null) { + String path = ApiUtils.getFullRequestPath(messageContext); + String subPath; + VersionStrategy versionStrategy = new DefaultStrategy(selectedApi); + if (versionStrategy.getVersionType().equals(VersionStrategyFactory.TYPE_URL)) { + //for URL based + //request --> http://{host:port}/context/version/path/to/resource + subPath = path.substring(selectedApi.getContext().length() + versionStrategy.getVersion().length() + 1); + } else { + subPath = path.substring(selectedApi.getContext().length()); + } + if ("".equals(subPath)) { + subPath = "/"; + } + messageContext.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, subPath); + Resource[] allAPIResources = selectedApi.getResources(); + Set acceptableResources = new LinkedHashSet<>(); + for (Resource resource : allAPIResources) { + //If the requesting method is OPTIONS or if the Resource contains the requesting method + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && + Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || + (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { + acceptableResources.add(resource); + } + } + + if (!acceptableResources.isEmpty()) { + for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) { + if (dispatcher instanceof URITemplateBasedDispatcher){ + Resource selectedResource = dispatcher.findResource(messageContext, acceptableResources); + if (selectedResource != null) { + messageContext.setProperty(LogsHandler.SELECTED_RESOURCE, selectedResource); + DispatcherHelper helper = selectedResource.getDispatcherHelper(); + if (helper instanceof URITemplateHelper) { + URITemplateHelper templateHelper = (URITemplateHelper) helper; + for (Map.Entry, String> entry : logProperties.entrySet()) { + Map key = entry.getKey(); + if (httpMethod.equals(key.get("resourceMethod"))) { + boolean flag = templateHelper.getString().equals(key.get("resourcePath")); + System.out.println(flag); + String resourceLogLevel = entry.getValue(); + String resourcePath = key.get("resourcePath"); + String resourceMethod = key.get("resourceMethod"); + } + } + } + } + } + } + } + } + } + protected static String getMatchingLogLevel(MessageContext ctx, Map, String> logProperties) { String apiCtx = LogUtils.getTransportInURL(ctx); diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index ef2c97419fdb..888fb3d348b0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -56,6 +56,7 @@ public class LogsHandler extends AbstractSynapseHandler { protected static final String LOG_LEVEL = "LOG_LEVEL"; protected static final String RESOURCE_PATH = "RESOURCE_PATH"; protected static final String RESOURCE_METHOD = "RESOURCE_METHOD"; + public static final String SELECTED_RESOURCE = "SELECTED_RESOURCE"; private static final String REQUEST_BODY_SIZE_ERROR = "Error occurred while building the message to calculate" + " the response body size"; @@ -304,6 +305,7 @@ private String getAPILogLevel(MessageContext ctx) { Map, String> logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); // if the logging API data holder is empty or null return null if (!logProperties.isEmpty()) { + LogUtils.fetchLogLevel(ctx, logProperties); return LogUtils.getMatchingLogLevel(ctx, logProperties); } return null; diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index 006b9d36cfac..4fb87392cf28 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -33,6 +33,7 @@ import org.apache.synapse.api.dispatch.RESTDispatcher; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.gateway.MethodStats; +import org.wso2.carbon.apimgt.gateway.handlers.LogsHandler; import org.wso2.carbon.apimgt.gateway.handlers.Utils; import org.wso2.carbon.apimgt.gateway.internal.ServiceReferenceHolder; import org.wso2.carbon.apimgt.impl.APIConstants; @@ -179,11 +180,20 @@ public boolean handleRequest(MessageContext messageContext) { } if (!acceptableResources.isEmpty()) { - for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) { - Resource resource = dispatcher.findResource(messageContext, acceptableResources); - if (resource != null) { + if (messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null){ + Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); + String [] resourceMethods = resource.getMethods(); + if (Arrays.asList(resourceMethods).contains(httpMethod)) { selectedResource = resource; - break; + } + } + else { + for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) { + Resource resource = dispatcher.findResource(messageContext, acceptableResources); + if (resource != null) { + selectedResource = resource; + break; + } } } if (selectedResource == null) { From d33301bc3e84158ee0b9dc10fc5a211d453082b9 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:25:47 +0530 Subject: [PATCH 26/38] fix for cors handler to process different method types (cherry picked from commit 5fbe312ae227be555f1f60c83240cc0fff838c72) --- .../apimgt/gateway/handlers/LogUtils.java | 52 +++++++++++++++++-- .../apimgt/gateway/handlers/LogsHandler.java | 4 +- .../handlers/security/CORSRequestHandler.java | 2 +- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 8bedc3a7692e..1e35f3381142 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -138,11 +138,15 @@ protected static String getHTTPMethod(org.apache.synapse.MessageContext messageC return httpMethod; } - protected static void fetchLogLevel(MessageContext messageContext, + protected static String fetchLogLevel(MessageContext messageContext, Map, String> logProperties) { Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); List duplicateApiSet = new ArrayList(apiSet); API selectedApi = null; + String apiLogLevel = null; + String resourceLogLevel = null; + String resourcePath = null; + String resourceMethod = null; String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). getProperty("TransportInURL").toString(); for (API api : duplicateApiSet) { @@ -196,10 +200,9 @@ protected static void fetchLogLevel(MessageContext messageContext, Map key = entry.getKey(); if (httpMethod.equals(key.get("resourceMethod"))) { boolean flag = templateHelper.getString().equals(key.get("resourcePath")); - System.out.println(flag); - String resourceLogLevel = entry.getValue(); - String resourcePath = key.get("resourcePath"); - String resourceMethod = key.get("resourceMethod"); + resourceLogLevel = entry.getValue(); + resourcePath = key.get("resourcePath"); + resourceMethod = key.get("resourceMethod"); } } } @@ -208,6 +211,45 @@ protected static void fetchLogLevel(MessageContext messageContext, } } } + boolean isResourceLevelHasHighPriority = false; + if (resourceLogLevel != null) { + switch (resourceLogLevel) { + case APIConstants.LOG_LEVEL_FULL: + isResourceLevelHasHighPriority = true; + break; + case APIConstants.LOG_LEVEL_STANDARD: + if (apiLogLevel != null && (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) || + apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF))) { + isResourceLevelHasHighPriority = true; + break; + } else { + break; + } + case APIConstants.LOG_LEVEL_BASIC: + if (apiLogLevel == null || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { + isResourceLevelHasHighPriority = true; + } else { + break; + } + } + if (isResourceLevelHasHighPriority || apiLogLevel == null) { + messageContext.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); + messageContext.setProperty(LogsHandler.RESOURCE_PATH, resourcePath); + messageContext.setProperty(LogsHandler.RESOURCE_METHOD, resourceMethod); + messageContext.setProperty("API_TO", apiContext); + return resourceLogLevel; + } else { + messageContext.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); + messageContext.setProperty("API_TO", apiContext); + return apiLogLevel; + } + } else if (apiLogLevel != null) { + messageContext.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); + messageContext.setProperty("API_TO", apiContext); + return apiLogLevel; + } else { + return null; + } } protected static String getMatchingLogLevel(MessageContext ctx, diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index 888fb3d348b0..ea53e56e5851 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -305,8 +305,8 @@ private String getAPILogLevel(MessageContext ctx) { Map, String> logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); // if the logging API data holder is empty or null return null if (!logProperties.isEmpty()) { - LogUtils.fetchLogLevel(ctx, logProperties); - return LogUtils.getMatchingLogLevel(ctx, logProperties); + return LogUtils.fetchLogLevel(ctx, logProperties); + //return LogUtils.getMatchingLogLevel(ctx, logProperties); } return null; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index 4fb87392cf28..26ae71feb045 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -180,7 +180,7 @@ public boolean handleRequest(MessageContext messageContext) { } if (!acceptableResources.isEmpty()) { - if (messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null){ + if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null) && httpMethod.equals(corsRequestMethod)){ Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); String [] resourceMethods = resource.getMethods(); if (Arrays.asList(resourceMethods).contains(httpMethod)) { From ba941b4a40e8ebd511a01addb5f24db40da0125c Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:35:49 +0530 Subject: [PATCH 27/38] including apilevel logging in the same logic (cherry picked from commit 626eeb6f7d87a50116b8fb335d0da1e3f39eddc0) --- .../carbon/apimgt/gateway/handlers/LogUtils.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 1e35f3381142..782964907e39 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -198,11 +198,14 @@ protected static String fetchLogLevel(MessageContext messageContext, URITemplateHelper templateHelper = (URITemplateHelper) helper; for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); - if (httpMethod.equals(key.get("resourceMethod"))) { - boolean flag = templateHelper.getString().equals(key.get("resourcePath")); - resourceLogLevel = entry.getValue(); - resourcePath = key.get("resourcePath"); - resourceMethod = key.get("resourceMethod"); + if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { + apiLogLevel = entry.getValue(); + } else if (httpMethod.equals(key.get("resourceMethod"))) { + if(templateHelper.getString().equals(key.get("resourcePath"))) { + resourceLogLevel = entry.getValue(); + resourcePath = key.get("resourcePath"); + resourceMethod = key.get("resourceMethod"); + } } } } From c8fcc63dbd1d1b8df49157cff6fd2f5bfe55898e Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Wed, 14 Jun 2023 14:06:13 +0530 Subject: [PATCH 28/38] limit execution of redundant code (cherry picked from commit db93dd85e47e8f3e77aed76155b30716f72d4aae) --- .../apimgt/gateway/handlers/LogUtils.java | 41 +++++++-------- .../handlers/security/CORSRequestHandler.java | 50 +++++++++---------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 782964907e39..cf27387841d1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -131,43 +131,40 @@ protected static String getTransportInURL(org.apache.synapse.MessageContext mess return transportInURL.substring(1); } - protected static String getHTTPMethod(org.apache.synapse.MessageContext messageContext) { - org.apache.axis2.context.MessageContext axis2MsgContext = ((Axis2MessageContext) messageContext) - .getAxis2MessageContext(); - String httpMethod = (String) axis2MsgContext.getProperty("HTTP_METHOD"); - return httpMethod; - } - protected static String fetchLogLevel(MessageContext messageContext, Map, String> logProperties) { - Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); - List duplicateApiSet = new ArrayList(apiSet); + //initializing variables to store resource level logging + String subPath; API selectedApi = null; String apiLogLevel = null; String resourceLogLevel = null; String resourcePath = null; String resourceMethod = null; + //getting the API collection from the synapse configuration to find the invoked API + Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); + List duplicateApiSet = new ArrayList(apiSet); + //obtaining required parameters to execute findResource method String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). getProperty("TransportInURL").toString(); - for (API api : duplicateApiSet) { - if (apiContext.contains(api.getContext())) { - selectedApi = api; - //break; - } - } String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext(). getProperty(Constants.Configuration.HTTP_METHOD); org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext) .getAxis2MessageContext(); Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); String corsRequestMethod = (String) headers.get(APIConstants.CORSHeaders.ACCESS_CONTROL_REQUEST_METHOD); + + for (API api : duplicateApiSet) { + if (apiContext.contains(api.getContext())) { + selectedApi = api; + break; + } + } + if (selectedApi != null) { + //obtaining the subpath vua full request path (ex:{resource}/{id}) to invoke the findResource method String path = ApiUtils.getFullRequestPath(messageContext); - String subPath; VersionStrategy versionStrategy = new DefaultStrategy(selectedApi); if (versionStrategy.getVersionType().equals(VersionStrategyFactory.TYPE_URL)) { - //for URL based - //request --> http://{host:port}/context/version/path/to/resource subPath = path.substring(selectedApi.getContext().length() + versionStrategy.getVersion().length() + 1); } else { subPath = path.substring(selectedApi.getContext().length()); @@ -176,6 +173,7 @@ protected static String fetchLogLevel(MessageContext messageContext, subPath = "/"; } messageContext.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, subPath); + //iterating through all the existing resources to match with the requesting method Resource[] allAPIResources = selectedApi.getResources(); Set acceptableResources = new LinkedHashSet<>(); for (Resource resource : allAPIResources) { @@ -186,10 +184,10 @@ protected static String fetchLogLevel(MessageContext messageContext, acceptableResources.add(resource); } } - if (!acceptableResources.isEmpty()) { for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) { if (dispatcher instanceof URITemplateBasedDispatcher){ + //matching the available resources with the message context Resource selectedResource = dispatcher.findResource(messageContext, acceptableResources); if (selectedResource != null) { messageContext.setProperty(LogsHandler.SELECTED_RESOURCE, selectedResource); @@ -198,8 +196,10 @@ protected static String fetchLogLevel(MessageContext messageContext, URITemplateHelper templateHelper = (URITemplateHelper) helper; for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); + //if resource path is empty, proceeding with API level logs if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { apiLogLevel = entry.getValue(); + //matching the methods first and then the resource path } else if (httpMethod.equals(key.get("resourceMethod"))) { if(templateHelper.getString().equals(key.get("resourcePath"))) { resourceLogLevel = entry.getValue(); @@ -258,7 +258,8 @@ protected static String fetchLogLevel(MessageContext messageContext, protected static String getMatchingLogLevel(MessageContext ctx, Map, String> logProperties) { String apiCtx = LogUtils.getTransportInURL(ctx); - String apiHttpMethod = LogUtils.getHTTPMethod(ctx); + String apiHttpMethod = (String) ((Axis2MessageContext) ctx).getAxis2MessageContext(). + getProperty(Constants.Configuration.HTTP_METHOD); String apiLogLevel = null; String resourceLogLevel = null; String resourcePath = null; diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index 26ae71feb045..852897ea2f38 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -167,27 +167,27 @@ public boolean handleRequest(MessageContext messageContext) { Utils.setSubRequestPath(selectedApi, messageContext); if (selectedApi != null) { - Resource[] allAPIResources = selectedApi.getResources(); - Set acceptableResources = new LinkedHashSet<>(); - - for (Resource resource : allAPIResources) { - //If the requesting method is OPTIONS or if the Resource contains the requesting method - if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && - Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || - (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { - acceptableResources.add(resource); + if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null) && httpMethod.equals(corsRequestMethod)){ + Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); + String [] resourceMethods = resource.getMethods(); + if (Arrays.asList(resourceMethods).contains(httpMethod)) { + selectedResource = resource; } } - - if (!acceptableResources.isEmpty()) { - if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null) && httpMethod.equals(corsRequestMethod)){ - Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); - String [] resourceMethods = resource.getMethods(); - if (Arrays.asList(resourceMethods).contains(httpMethod)) { - selectedResource = resource; + else { + Resource[] allAPIResources = selectedApi.getResources(); + Set acceptableResources = new LinkedHashSet<>(); + + for (Resource resource : allAPIResources) { + //If the requesting method is OPTIONS or if the Resource contains the requesting method + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && + Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || + (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { + acceptableResources.add(resource); } } - else { + + if (!acceptableResources.isEmpty()) { for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) { Resource resource = dispatcher.findResource(messageContext, acceptableResources); if (resource != null) { @@ -195,19 +195,19 @@ public boolean handleRequest(MessageContext messageContext) { break; } } + if (selectedResource == null) { + handleResourceNotFound(messageContext, Arrays.asList(allAPIResources)); + return false; + } } - if (selectedResource == null) { + //If no acceptable resources are found + else { + //We're going to send a 405 or a 404. Run the following logic to determine which. handleResourceNotFound(messageContext, Arrays.asList(allAPIResources)); return false; } - } - //If no acceptable resources are found - else { - //We're going to send a 405 or a 404. Run the following logic to determine which. - handleResourceNotFound(messageContext, Arrays.asList(allAPIResources)); - return false; - } + } //No matching resource found if (selectedResource == null) { //Respond with a 404 From 3552d93b4eee3e485f45d84f88c6f26494850132 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Fri, 16 Jun 2023 10:24:21 +0530 Subject: [PATCH 29/38] reset resource object for every invocation (cherry picked from commit 1f8e1dbb04a7f5887933298a3d2a6420e2d4d48d) --- .../apimgt/gateway/handlers/LogUtils.java | 5 +- .../service/dto/APILoggingConfigDTO.java | 50 +++++++++++++++-- .../swagger.json | 9 +++ .../api/devops/dto/LoggingApiInputDTO.java | 47 +++++++++++++++- .../api/devops/dto/LoggingApiOutputDTO.java | 53 ++++++++++++++++-- .../runtimes/cxf3/snakeyaml-1.33.jar | Bin 0 -> 331715 bytes 6 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 features/apimgt/org.wso2.carbon.apimgt.rest.api.service.catalog.feature/src/main/resources/runtimes/cxf3/snakeyaml-1.33.jar diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index cf27387841d1..20629ab22602 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -140,9 +140,10 @@ protected static String fetchLogLevel(MessageContext messageContext, String resourceLogLevel = null; String resourcePath = null; String resourceMethod = null; + Resource selectedResource = null; //getting the API collection from the synapse configuration to find the invoked API Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); - List duplicateApiSet = new ArrayList(apiSet); + List duplicateApiSet = new ArrayList<>(apiSet); //obtaining required parameters to execute findResource method String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). getProperty("TransportInURL").toString(); @@ -188,7 +189,7 @@ protected static String fetchLogLevel(MessageContext messageContext, for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) { if (dispatcher instanceof URITemplateBasedDispatcher){ //matching the available resources with the message context - Resource selectedResource = dispatcher.findResource(messageContext, acceptableResources); + selectedResource = dispatcher.findResource(messageContext, acceptableResources); if (selectedResource != null) { messageContext.setProperty(LogsHandler.SELECTED_RESOURCE, selectedResource); DispatcherHelper helper = selectedResource.getDispatcherHelper(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/gen/java/org/wso2/carbon/apimgt/internal/service/dto/APILoggingConfigDTO.java b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/gen/java/org/wso2/carbon/apimgt/internal/service/dto/APILoggingConfigDTO.java index 0246b4742c8b..99c535034ef5 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/gen/java/org/wso2/carbon/apimgt/internal/service/dto/APILoggingConfigDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.internal.service/src/gen/java/org/wso2/carbon/apimgt/internal/service/dto/APILoggingConfigDTO.java @@ -18,6 +18,8 @@ public class APILoggingConfigDTO { private String context = null; private String logLevel = null; + private String resourceMethod = null; + private String resourcePath = null; /** **/ @@ -27,8 +29,9 @@ public APILoggingConfigDTO context(String context) { } - @ApiModelProperty(example = "pizashack/v1.0.0", value = "") + @ApiModelProperty(example = "pizashack/v1.0.0", required = true, value = "") @JsonProperty("context") + @NotNull public String getContext() { return context; } @@ -44,8 +47,9 @@ public APILoggingConfigDTO logLevel(String logLevel) { } - @ApiModelProperty(example = "all", value = "") + @ApiModelProperty(example = "all", required = true, value = "") @JsonProperty("logLevel") + @NotNull public String getLogLevel() { return logLevel; } @@ -53,6 +57,40 @@ public void setLogLevel(String logLevel) { this.logLevel = logLevel; } + /** + **/ + public APILoggingConfigDTO resourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + return this; + } + + + @ApiModelProperty(example = "GET", value = "") + @JsonProperty("resourceMethod") + public String getResourceMethod() { + return resourceMethod; + } + public void setResourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + } + + /** + **/ + public APILoggingConfigDTO resourcePath(String resourcePath) { + this.resourcePath = resourcePath; + return this; + } + + + @ApiModelProperty(example = "/v1.0.0/pizza", value = "") + @JsonProperty("resourcePath") + public String getResourcePath() { + return resourcePath; + } + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + @Override public boolean equals(java.lang.Object o) { @@ -64,12 +102,14 @@ public boolean equals(java.lang.Object o) { } APILoggingConfigDTO apILoggingConfig = (APILoggingConfigDTO) o; return Objects.equals(context, apILoggingConfig.context) && - Objects.equals(logLevel, apILoggingConfig.logLevel); + Objects.equals(logLevel, apILoggingConfig.logLevel) && + Objects.equals(resourceMethod, apILoggingConfig.resourceMethod) && + Objects.equals(resourcePath, apILoggingConfig.resourcePath); } @Override public int hashCode() { - return Objects.hash(context, logLevel); + return Objects.hash(context, logLevel, resourceMethod, resourcePath); } @Override @@ -79,6 +119,8 @@ public String toString() { sb.append(" context: ").append(toIndentedString(context)).append("\n"); sb.append(" logLevel: ").append(toIndentedString(logLevel)).append("\n"); + sb.append(" resourceMethod: ").append(toIndentedString(resourceMethod)).append("\n"); + sb.append(" resourcePath: ").append(toIndentedString(resourcePath)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.internal.service/swagger.json b/components/apimgt/org.wso2.carbon.apimgt.internal.service/swagger.json index 9a89d4cfe705..5428e9e9170a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.internal.service/swagger.json +++ b/components/apimgt/org.wso2.carbon.apimgt.internal.service/swagger.json @@ -1830,6 +1830,7 @@ "title" : "apis" }, "APILoggingConfig" : { + "required" : [ "context", "logLevel" ], "properties" : { "context" : { "type" : "string", @@ -1838,6 +1839,14 @@ "logLevel" : { "type" : "string", "example" : "all" + }, + "resourceMethod" : { + "type" : "string", + "example" : "GET" + }, + "resourcePath" : { + "type" : "string", + "example" : "/v1.0.0/pizza" } }, "title" : "API Info object with log details" diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiInputDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiInputDTO.java index 3e7907e573b6..92541b85019c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiInputDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiInputDTO.java @@ -21,6 +21,8 @@ public class LoggingApiInputDTO { private String logLevel = null; + private String resourceMethod = null; + private String resourcePath = null; /** **/ @@ -30,8 +32,9 @@ public LoggingApiInputDTO logLevel(String logLevel) { } - @ApiModelProperty(example = "FULL", value = "") + @ApiModelProperty(example = "FULL", required = true, value = "") @JsonProperty("logLevel") + @NotNull public String getLogLevel() { return logLevel; } @@ -39,6 +42,40 @@ public void setLogLevel(String logLevel) { this.logLevel = logLevel; } + /** + **/ + public LoggingApiInputDTO resourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + return this; + } + + + @ApiModelProperty(example = "GET", value = "") + @JsonProperty("resourceMethod") + public String getResourceMethod() { + return resourceMethod; + } + public void setResourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + } + + /** + **/ + public LoggingApiInputDTO resourcePath(String resourcePath) { + this.resourcePath = resourcePath; + return this; + } + + + @ApiModelProperty(example = "/v1.0.0/pizza", value = "") + @JsonProperty("resourcePath") + public String getResourcePath() { + return resourcePath; + } + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + @Override public boolean equals(java.lang.Object o) { @@ -49,12 +86,14 @@ public boolean equals(java.lang.Object o) { return false; } LoggingApiInputDTO loggingApiInput = (LoggingApiInputDTO) o; - return Objects.equals(logLevel, loggingApiInput.logLevel); + return Objects.equals(logLevel, loggingApiInput.logLevel) && + Objects.equals(resourceMethod, loggingApiInput.resourceMethod) && + Objects.equals(resourcePath, loggingApiInput.resourcePath); } @Override public int hashCode() { - return Objects.hash(logLevel); + return Objects.hash(logLevel, resourceMethod, resourcePath); } @Override @@ -63,6 +102,8 @@ public String toString() { sb.append("class LoggingApiInputDTO {\n"); sb.append(" logLevel: ").append(toIndentedString(logLevel)).append("\n"); + sb.append(" resourceMethod: ").append(toIndentedString(resourceMethod)).append("\n"); + sb.append(" resourcePath: ").append(toIndentedString(resourcePath)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiOutputDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiOutputDTO.java index 5061d1ada543..9828ff25df63 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiOutputDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.devops/src/gen/java/org/wso2/carbon/apimgt/rest/api/devops/dto/LoggingApiOutputDTO.java @@ -23,6 +23,8 @@ public class LoggingApiOutputDTO { private String context = null; private String logLevel = null; private String apiId = null; + private String resourceMethod = null; + private String resourcePath = null; /** **/ @@ -32,8 +34,9 @@ public LoggingApiOutputDTO context(String context) { } - @ApiModelProperty(example = "pizashack/v1.0.0", value = "") + @ApiModelProperty(example = "pizashack/v1.0.0", required = true, value = "") @JsonProperty("context") + @NotNull public String getContext() { return context; } @@ -49,8 +52,9 @@ public LoggingApiOutputDTO logLevel(String logLevel) { } - @ApiModelProperty(example = "FULL", value = "") + @ApiModelProperty(example = "FULL", required = true, value = "") @JsonProperty("logLevel") + @NotNull public String getLogLevel() { return logLevel; } @@ -66,8 +70,9 @@ public LoggingApiOutputDTO apiId(String apiId) { } - @ApiModelProperty(example = "12d6e73c-778d-45ac-b57d-117c6c5092a4", value = "") + @ApiModelProperty(example = "12d6e73c-778d-45ac-b57d-117c6c5092a4", required = true, value = "") @JsonProperty("apiId") + @NotNull public String getApiId() { return apiId; } @@ -75,6 +80,40 @@ public void setApiId(String apiId) { this.apiId = apiId; } + /** + **/ + public LoggingApiOutputDTO resourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + return this; + } + + + @ApiModelProperty(example = "GET", value = "") + @JsonProperty("resourceMethod") + public String getResourceMethod() { + return resourceMethod; + } + public void setResourceMethod(String resourceMethod) { + this.resourceMethod = resourceMethod; + } + + /** + **/ + public LoggingApiOutputDTO resourcePath(String resourcePath) { + this.resourcePath = resourcePath; + return this; + } + + + @ApiModelProperty(example = "/v1.0.0/pizza", value = "") + @JsonProperty("resourcePath") + public String getResourcePath() { + return resourcePath; + } + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + @Override public boolean equals(java.lang.Object o) { @@ -87,12 +126,14 @@ public boolean equals(java.lang.Object o) { LoggingApiOutputDTO loggingApiOutput = (LoggingApiOutputDTO) o; return Objects.equals(context, loggingApiOutput.context) && Objects.equals(logLevel, loggingApiOutput.logLevel) && - Objects.equals(apiId, loggingApiOutput.apiId); + Objects.equals(apiId, loggingApiOutput.apiId) && + Objects.equals(resourceMethod, loggingApiOutput.resourceMethod) && + Objects.equals(resourcePath, loggingApiOutput.resourcePath); } @Override public int hashCode() { - return Objects.hash(context, logLevel, apiId); + return Objects.hash(context, logLevel, apiId, resourceMethod, resourcePath); } @Override @@ -103,6 +144,8 @@ public String toString() { sb.append(" context: ").append(toIndentedString(context)).append("\n"); sb.append(" logLevel: ").append(toIndentedString(logLevel)).append("\n"); sb.append(" apiId: ").append(toIndentedString(apiId)).append("\n"); + sb.append(" resourceMethod: ").append(toIndentedString(resourceMethod)).append("\n"); + sb.append(" resourcePath: ").append(toIndentedString(resourcePath)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/features/apimgt/org.wso2.carbon.apimgt.rest.api.service.catalog.feature/src/main/resources/runtimes/cxf3/snakeyaml-1.33.jar b/features/apimgt/org.wso2.carbon.apimgt.rest.api.service.catalog.feature/src/main/resources/runtimes/cxf3/snakeyaml-1.33.jar new file mode 100644 index 0000000000000000000000000000000000000000..5a95195e56b2aab6de7e00b681244d0447dd8b12 GIT binary patch literal 331715 zcmbTc1CS`emMz-0ZQHhO+qP}nwr!iIZTqylPuq6)KljeWd-LbLnYi;Rq9Q7ya_`Eh zSbOEpwNgPE7z70X0s;acgpErT;6GfD03ZOeqAG&4l5%47-;)3UzyJ!;;1K^90rc;~ z6#mO#l)oeXSFo(0oTQkjvI?E7Sgh)R-2nqikN70N296p5YhVayl?o2UR3WO$N|To5 z$b>B3GErl58?r&aUp}%FH3VV%cpkewPaZlwg}JrD?>AT_#sT1iPTtKd6D<;z=6THs zis%8)LP!vi@mTKy$xAA^c7r~fi$w9+9I9A>HZugmA&1v(Y*?P3K7I^B0%ONNJmT8s znL-v=TiK#`gjetig(j7BTtAsK#~l}mDN>+G3V4VT8LO|oXh}RvIeAnkG$3^fOWmuM z^H1=DJwKS(4-~riAaw z5;{hskzPlp{C3wlQw3N>W)BGol7&b#=W#eFp~tOrY%$1z+i%U<A7RH%Y-kkk@mydL`9MS)~X=2NGb*9s0+rOBafw~XqJnr_HcZAg#K6p9lyb%+@lCk zX1mVSYbZFWJJ{!g$sRPeoe%q8vDl z#4=Kbgu1fyx`{w@+=MAK*E*)>vu+&mwkjZ6y7W=AxuCS<)1y{) zK5?hpP?Y0jHz#)MEpnPx8&_6$#L3(I9CxnBh}PmfX*T>d?u@FRdvlI9u8jHMC3?cC z?@1Q6cK50uo7M5)sGkm5m->)-5av~t+acV4(TCO&%e=4Zc-?dfZ8q22a` z{||89)Pn!k{)`T#5O~^>g&;drFo{*ZA2Y~|q<2P6G%-#LtTg-p&|NWay{u6;v{>!uRu(i3uwRYZQ zyZ817l~4XiqLiGntE-e>SaHq4ez_z=E|33M4wR5El0l+@{C#ioxodw%@Crn!kcPvV zK3jqoxIF>{P2+}MKhdwIXtBM=0xj`r#o`7hh8D+r0DgC{LQ(GgadfJ`WKSk3#b*?+ z1%PW_FD5OOY`hjb4;zP@LSP?>n?$$eZco2`lLIUkDvVd(Bp|rEv%}Rcj&psxXK?xL z=;;U=f!GwxQB3j7U|>4nIEqXk5l&%lWoxL04kF)R-}mvbHwSE<`c{0#j`qnO84*9U zD^gmXGdx^d3fUkkb^m88ABgeAIw&P!11ldCeCy0>A_l1%=on9U{=UgBP;L zI;>zuA+(SgsWzz&r0ZAy?W3*RHl%+D& zG~%u}@gfokM=EXW_pjjo;!B11{&go0iTS1f}@>{{V0dbdL zp94;3lo0#FW){*jm$*R~bP*Q-SfaMm9yg?80)z6?1Nxjs<=aKTMUoVwg+Wc^TL=qW zloqZ+GXG{prWlii;Yirm3z0Nt`Yvc0NceM`zhQ>dd0wdDq^-DH9(C!a{8mS2bz5mj!T zQxtJ!{Ha{>Whn%~Qm&qgnyn7%+FTO65Q3 zYl7#Jy}_(Ia8%->(@45FBx>*L4oToUBTfoA1q=0@n;_g9@C1!^|7qZrDFRwXGzn+W zlBB@q8W5m;J`XFB>a%80)M&zg;3$9{QUg?#(S%%Mu|qwLZ7LfRpEVqsR#nIZ=aJ83 z9TWrk(5*JfUVB0{811|~s*&so*uhjO2WWMKS)w?mS}1S}ms<+jHC^FD!rx$tXo&QY z(g@ay8Jp(uRKb+ACn8yh(ZN=!0MOCKu9%cQx$Ul1DNj=R&96FB&Ptpzwot=Q5jiN@ zXxuZ&tlcG``+kTHX3~rPjqpi(>Q?n`o}V?lxH)&LnrKnYB!Wo1)wc*Iv4@Q{J3g~CHy^Y*Hur4m-*>Y>okBHuFFqnVwMFb zGRF;UZrQ?kpI6EY7g%p!U959w4sY+)S|u4iqGk*bd9&?S$x(# zw@Vi=xRe(jZSQbV4g)S+T`%L~6*pdTU*7=7oC@oh!g_6h`ZSvnD)+>o+d|<{ro*~p z9a~cc=M}cAaP-Tch?ilz4>6_!t*?Q3g2;!lu)I)>sEh;h zMjX7C>eLAeU4H)+Dck`0Z4}^GQdzLwW3e(-Pm$-RV2f>!V^}(7|1+P$lm5Hyf9toIQE>5sO2igV>fMMFX@`* zV&0PER&I>A6A&75W>Q5}gs(&J`i8NYo4Pbr0Nx~^8{sDMQO`~M%64eLa6?&nLk3Vq z3-afcCFNBG7F=Q+wwX0J7{KtKNy84kCaCtDJUtoZqg5dn@N`IuuN6&hClCdB`U(>^ z@i4!6-dPV!mdY%bgh-dul0G{+fuOu=Cw|U09a|g2=tpm~%sP6o)rM$TfPmfh2%otW zGiTmT6mfZ4{^}Yq**vkPptc?eBc9fu2sQfAa71ECrN>*rY2A{(KqA4ix%}=q{s8hh zb;GwV4Ebvej;|1C`?`7^$id0pqCElg)WK*T;!Af5QNsvfWuMeqXx>X({Xsnpl1xMO zst|o|bID}7v9ZI=95PPd+9C<&(IB=HNY=`Bk-I^LOJ&=|A-^>f?XodgC}8|Rar!qM zV_y>KlzmH}-(jJE1%_`gXf>%tnNWUsYc`eFpow>q+t&$f$oi+B^kk!jtM|q(nul;B zgS?E517LlA3i@7A2iQn9tZ*%MvPT3`g?^yP7c8>~f&8R`!LS!1?s^DBgcjP@EDA!{ z1UF<=i9KU9pR5v0Z=4Z8*~|?VtGbKKpoxzfs+pp zF#V&>DdCSb04TBb6B^?CNTiaKy>4FNa}rCxip!-hb)~1RCb9J8ud#OKi<4{nKtsuC zN@%sE8LCAi_()yVGuMteVAO&iwQcKb3%#g`hJO2Y^-^Qoz>Hwlcb&SXhRnE-aKk4Y z>&dGh82FEp%q=re_jT>hsX*Dw9b(wP4uJ6k%+G<*14azGe z+S(ON$;t@_1JQG}UpNXBuj9p_V}ABcnj_*fhmJ0sxXxZVX|HvsOb07yYF@$c2DX5u z$SPizlic>Fo}Ht_0?j8Q;tJ>dYP9<3ibE}pn{95+NaPx2uCZS3z;8I7f{&ahrHkv; z6f|pu;9RysGrC|akZugW(w-t$lc^vLqHQfEiPAX3`wYf)^PIL!%B>qb^L!EG1uYmm zneTtjt<36xD)aUjzxHMd-?(ET(L58dV15dzW0b1{**%)=ZNI~I(78vMLemCjiC{86 z=8e%PCeoUR$Hk3ZF~Dq3#kb)maoKz4?49et=_$^rNu(T)o6`ZgdjiKHC3F@G&l`38 z@$++iy4ct~Qp~}sh0Vbs%%+y&CCa#?wZgSs8pzbMfvbt;ybsae@r_0iBY7u+` zP01OXc0ir|%R`)$+@$MHmaqnzwFU5FpQ9!sDGhqSx~L3lj^JA%xb}JS`!!fdyZw|V zK<0ot*D(@nIU%zMrAtth?;RKL5zS=ie13bN!7kl4Hm|$wG}2lLb*S}4PP(|)Ta|v%;2u zEw0h8Q3;&ScV5Y~*UStDWxy}ED^uHrJM$V$URy6B@h(MG(D=&(-@GfF+A^;KlBu$% z9!d?Kz4}ybKDwFEik0S(dp>0D1i;Q@TuiTK9py<@e)q81rXNC9_$?~tL)m+NF>+v{s6(1?yQE@{ zvFf#3h&lWMY|b8B*fBE0$g=NY9Vstw z@%OT~9{4p7Ud@?F*sGe0ZoM`1dcILUyNP*2JG5ll6B0h+<#Byt`8m*z?7$Q(^0NF5EaT>tGq#mA%9kGGCLU3i1hqXT88y;7n)6F*X**&=9Q`HT##qAi zb7kD4N-PX==I*un=pJB7^a=&1je~Lqc*apBZ>ByH7~uG=pI*vh7q@)Re!Z4}iGaxO z!m6J30a~+Nha_4So#w;-UJ;^uu}!lf;wtEfRs1(fp3dp8B}4yap_XZnZ>Hm}V6YF~ z@HdVAX-^U_yfI3Sy^)@Z_;|EyJK=DppG#{@FDQ? zu^4S7zU~(FW3xXk(ecp<*TsNKYLC~LOec|@moRL(K?6}=^$ZidE_GtKUlQ`%TeJ479rqo`PerLS*uC=YURU%?d2W>(@TL0 z!C2A??M3>8?uq8b@RR}GCpSS>CVe9w*H_uuoLM$IXSHFsqfrl%&gMeuCTr!(*@4Ot zyO0<+eAa05ikEoD{g7ai>Yk8A<666LR>D>05^3Y^-9!Ivns%g&45bT`kN zZXT62N5oGpp&_=SGX>Y|#h{Eb5^0Z>EoqtbVSjRBI^p9#YKdXptLGd;!|H?nX$5%T zTO!*L5jX0&##bUI4XeJ3T;)d8zAK!;QJ+=LS`DnZ%3225R(K8OZ&7Z!Tk2oMj-Yvc za7^B(W$ge%;tpPxJhg~iCa4DaIXxhX_MMr*?AN{wB7yLhma{V#bvqNz1K{*H50RSz z?2wMG>+t7Rw#rr;t_e9Lk{A)Xgd;JVGJ3)xWr9q+C@;OF@G#bnzjCjd5M)iIF>P49 zc?L(JEZ(}mGH5-7eI*jzVXbapp`oxsvP>?1*Wdv@k6b0$N}1sdN7!n>@0Rh&?Ls1^ zV098Z&#{)Xy*yCJfsESp-5E`t@VMcicz3e3f*l>V;l>$TYTn9 zQ{U?U8c@pD)iIrP^4@L4&=lgU7c)NjNUVweyuG6VhmzThrSW8}#b~~4Tp7dP&p_%A2p6E6T%!bfr>ko_Bp1DI#@f&;r<+h)lqtmmmAMyNi*s+$hHd(xo>J{p= z6$p0r8Mtr!=AY6;GPBe-b{-z0c(a42?iWd8u?C@%hnsLXIVWZoaWLX|Rjl-iB#Nh! zhlkGp$~~YO@w>Wh>>hsVM`zn!;N*~3Xq1PhZSH!-LZd~r_li-1FcUSqDR&VwZeZ7W z*P&fLRZ8zfv1zL5sMqjwjvsDoiKm$4fNa({)$29*gKU`E4Szp1Tqs3vp&P;cSPq=WTF0OC32E!QNfTGcC-Kf5(F@OH2Ca2%| z`p6PWsmWswuOud{eRAQo)LW`Ry5^Kp83!HYN`s68isB+rMGxcTn`~vyEL6_JK&?5i z4xFwgjD9g|XR$L|H?xgLq%%^LS`TY?83S7ZXcEH=dYmOuy^UnKIk6a&T!7R1}xs|qWhO_JWe=xn)G_^R6F4&X8pYc zCWuDd#&tOzR?R_%Y9VjdyjNBJfWS(=KzKhhG=pdCKfwP`;irinR@_(dKLjHTq|5%LtJDY!g?4N=Enx1L#pA^J@XpH}u?|(`m;%fU>yp(rv zv9z~yCK0o-cUN}tv@xYKwlQ>ePF0b1#ui2R9`(Ak>TSg3biCb^gh@=HAPTvSh#{V6 zYluV&TvJ2XZ%td9B&*h4u`;E?;cx)B&gpR2PoP#5D3cI85<}&WDl+e(NGbwQOEoKV z?|bX|xX62ZsMq%gcffQff-n*tpjsu#Nxf|glB{_!48G|Z3crAY>KIUGe^W@gtph^6 znOOhRJQ_}mx#>eUkr9RPnI<&;Vmj?uOk=D!2o5vgQ|J**nADy#$8ytW%20vbX4^rX zwqt<-8wL$JR$F#`!AiZ-@Z=q)QOjoSIz+q5yVQssojYV1rckG#(=W=13wS>wEpoceC>b)ovqUAv(rk61w^aHha>;oT_M%h1N-5_?aB1;|x5U%y zbQ7kBUa9oLL{Tla%}Ui}e#sUjXI^yfpCaL<6gLWX=Zyy0ZETsT*N8cZuCc%&btNNGf}yk zW9a5i6Se)WFeDxW>1Q`M3WHBAahRM6%|UB~$BfjcN@y%DigLOtV~A#`@>|7OcIh{( zj^86zYA7;YM7M|QeohpW+nWF&b5q)FS`_bW-moaDYK|GknQADV+lZ4*vHse@tZwl^ zA{6vbD)Lb3^*7RuwAcLCxogg~^{&4i5dHR@xmEyPPVSIuq`r}&vDeX{SFhdrvfo4? z`#b0F(vMrex}Pw3J6pT@M71{?LG3A>B6Rm8ye9>-q;#kP&)NKww-^d~Dh9R@?+_bE zM4AIph8~es%&a$g%fME~N031L2_p`1V~xuzWWKPDcz;ykgK8vLGC#pn$RHg4 z(-9Sxb3)c`yBt2k{10Ra=T%F5(bsRfu{mK4W#V6K?iv!oZ`PeQCRMUMgg%Xg9gKPTw_iC|^#a%h0Vs zn@Vd}dcI21#;hQfN7`AuhVZ6$n`gjeJt}_li@7WmN501bAv{yg{he-Q%7fl zA#RT!L+-QYQmvy$mB(RL&7-f?hOzar?bMpq+;L?-nU5l3P-nw1JD97M#fcx0NWU*@ zHuGWwhsQ8kqe+64->AEiXCB7BrC}@3D^~f5lO2mSxeT&?SB*E|!m2Epml(Lu?}Q;g zj1&u1|5Bn2Dyru!>sP#w3jb}u;x`S<&dC{ud~}ki#nhL%tHm@`1OdfI^j_J6oFWkA zJh2omLf5f!uz(k^-BRGcO#HBQT z;eiSaqx(dfTm5^s>*x-HD|wdL+nL9;NPUcp2Dcbv?T%~|Q|ql7qgKOoiTNw3+(1|y z(A}jcjzd*EJXRL>>$Ehh%>w5h7MJn52@TiRs0eX-A&RkOE!qg;C^yM^#eG1^ZfWvE zrDf-b8gS@!9}gKnbV5x2umUaU+GcsthAAfcchzvg%ORlrrz8Nj0NeZ`>#Omwd|3V+Bx!8cCUaFyBkgl`BO!NY4A@f|VC z`CL&&D%da|D_AVfJ`~BK4B|v#9&bo8@ve}k!jMI&?jHCcmjJULibihB7~)*S!!0I% zVhCfRYg)#vADKI9`5wnK7?E5gQ72c0w^zB}ovnJ^@bZ zjXzmqecpE`a4@rEP-S*UfWDTv4V?1dBOd5O2j(9O3n=b>UcPn;x0H&e&UDPS!`@khX;^k6@d#IOa6&$Bq@Ty3;rpvAha(;P1^ z{oKP=-uLIz6LGID%y~7O zaMRf>@7h7$LaXdHcatobZMySP?Z&8s1srA+?AR50Tuh)YhSOm&W{%!#Fz}Ksu1DHX z_?fh<6o}%Q^-3>SaFU%mw*5KR&{8{c8yAa>zJh1kgxtDN9p{b2Z<(RLe2MQO`_c-5 z++E;)!8z7g79<-sb3tsGF_sp_-BC>#77|8+1as#I2~(JN_jI$M6NK}o3im+w9D$Z$v#_J5Qi?t zRnZU_i5CEAx;~fi>nr{d)HUR}2Aq=`0$~?5F_A11(ds+JD#a@Neo=kXO zGI{R&tLqUvv(StDHaHWA|xl>k%{RRz>ZBl~G13_c2uO|8dtyY*y-9M{JUg>C zq{u*BsIs(GWlG+f%b??wL-R8pinVG_RRP^+O_}k1D$*ksD+=(g)+rU~R9%^s%TT7p zST?`=1Wu)_4h@mJGURMY+0&PRwyHB-f>i6o&yJSE0OV6&hF?^be+j$`_!f#qS0%4C{C_9nQ>pc*ZX-WYb~1i}kitXKSC+kxR5F zFwcS3gk(!lvo;(2K_}yWI+Rbh%u}5K8rtN`3Da8iywZO~Suq-*SWW|xX?4uE${wAd z5nO$SPJvQ?I>_LaBDAk)?UFp)+_!d*^z3zW6lfnzUc*ULq1N|6pWiidk?hoFc5N-& zL`~}%)jdg7Q*Iq{Z8aj7)mn~nv%)bX!?(UqW;rh%ndPBLgs)es%g*Z4G64TZ+w6v+ zBOYAykO~XqMKodAj)cc-_MkiDyJs5AD524x*^%m1*jkcpi&SRSyM)yU=fH=USQif* z2?Pi<%Qu!3gD@t7GeuEMLj08xLlEtVhKzyCun<;cmu1SFrL8AV?!W93T^aDJ&Cw#o zp8;rvtR1k{(c}TJ%+vwF6pt5SeksebioI5Y?XfyFaf5fh73+xo)_()Zp}$n;RaeWx z{YncL`O%>JV!(7?jT&`(9hqV2`CHE!2wMH}3gLUIuUZWjN(d%n=T)SguVB%Sq_8C7hg}&xA{3fqej#VfL zadoc%W1NVI)d|eqkhJHRaBa~IbI_5PJ6+WJ?Gy>;!`Zue59$JIN zL$uOdo^B#LLcNlHu=Ph4*QV zkaiT;Y4HNofg1w9V%IA-S2*)Y|J7}5-^e^>nEqi|sps4oG%JgrH1okdE-Q;~+OcoD zeP!WUI}3h9&|f#uuedT8NYzOWN_C=>LWA_A%pnzrT-FnIf5lW6PWfDL<&xY^FzOKS zt5y-$r1BX{HBn&kT)p;>mt{G!{=v}tJpVrgkyx$}A&ZucmFAh%E;;{V?XJ->!dXlm1IVRq9U?FgnzAkvQmN~v0{xPOJ%Ml%|Y8Pm*xo@ zw&_Rir$Qs_9ImU^E&IiAzDHGV+_?=JM#u|_4~Mzlmz$dvn)4VsLpZ@C!$;^<+3U3{@~Z5f|#+#590r3 zy&^MbO_#v4EbP+SOamHwNF%;suhw4lwXoYrQZ_w!e*uz?tW$x`v*t{dxu@_Jd1!62 zM3-GNa`~l>+f23L9wA#kp%r&Tn>b3SeKMFLjTU+OWsnFo1X_KNp|?cp#dBA-H&E57 z>V@5OJsIZ0vt+%iLWG%Ce7*A9_uOpCErDSlBJWD8;h3d*!(H7v zaz0V0_AKp4Hrh4nd3c6-{TGV*wCyb`iJ+`I2!Mgk>yP}vW9hClJA>LNb2>SSV&xGYPvqYZKob0b$-<%&3b9`?4RnP z4cxkDfp!^v9|^dxyG9W@Or@$R=tsQVvT%7_JabgQrevG5qatV!xtx8gf=0QyO_o_f zgD|lrleg$g!4`&FoJo2XBo6tjgqx4-1NuE91bz3jK zk;#{(C#9*7O$7?|D2W-lOJfSw7wncX+))b8K=fg+NW{;RW}`pG2RZ(D*LRU9(;wA~ zElZ>{k0(pkF6DpCP}K^|L7*ICBcZ5aU9TDtds0@|=u!ADLm&pY_X`kXW@i z+yZbd4O`^75if}3-N&PG@1+v7c?iVgnHxfpO@thjbvrx)mhK?yz&O&yK5cn|wW8uE zgZ&A#l$Ogq>J^kw**-YlK+1jGWv(2naoux{SCX2-m05bjJ@z4o59JVB=^ydC8vGkY zMjRb%^ADJJ^@cwBVjk&|f2QwWssB;lqS~i+!N33jgW&&Nd6WGM<^6AEovUu`gQJSd z@BXkZ&bDFlV1=cX##VdQHgUYb=DT3_P^EoeBnb?ul3_!ZZRu{Fo+-JBl3?Xq5CjDj zq*fUKkC1?tW>l>LT2u520J>YT`&g|1bTa2`W^Qgy?!H-z|Gecrx8*(iljD8;v*Y{F zf1(c>VE5V${(CRm?ljQ8(-4{GDvb6P=BZEiKoe;$(IaozU7|YeGg)*KxsRpvy(NRb{ zDjKE-Q4=loyQ840=saYX$w4kMii*^fyl3hcFU^EeJ`q%S?kyf%_`yW+yA=6noZyIv zN(8jj>T(VTJxH*j=hN<~a5i%UV9M%s;uf^7}EFT=Wv zDfY2V%U&FmlTz9|6);(Lj=lVZIN1qEl^q_z9V|4H zj6f&SloJ&dRbLY#Ktlo{toQd)>prF>Q|I8kT=6E8p@O%QU@?n>rlna3!UTNM7{o$R z&kjOS6G3ei1SPa@`tGJ-j)HNaWGo;^o1Hq%*tQ-@Q5BZbDp(z!X`H?jCORnN{qhOL z(2}P05i9u{vk35gR8&a_>2c9g6gm9>wkbDBCX$;o1tqRSC}GR>>Y4G+&Mu6M)KtkS z6k93#Bx!$A0?Hh0D5P6KA(0!7qa=mJRgJQ>2=vv1UX%4cJ;1p zYX<2f%vVTL+Emh1`}E@^!IljZx33#d-7GTnp&`i0a8nxAlR?X_9BP%jx;~jL%5iED zezmnVQ6E3m#Edw`B&@q7)ESdYlN;x7t$HAqw^NUA@R2HAzFt->Je0$}v1%j-d_z~K z-1+Pk#eq9Dqxi?vYBb24sIx+3gix}7_Fk=RiO*{vtz!kcKO9$YUG4zBVG5dCQU|`f zw;^1FK9b?lvoL=c02aKGU8I+P5WKe`T_hyzLt+bHNDrfsvY6!)ImX*CW;nKC7aE!2 zEQH^CpZ>NF-7Y8_(?#FUo;khAHXPDx3wkL4{rr4u14B1vY%DngK@pP&4fRRGaSXn~ z=$BJ1sE8-yf*jd*lse~FcSZsW3nJEZ3(V>R8KsmGq-?l&7;Rk^6T2EgV}(_qCL@6b zpih@UfAR-yVu?KN>93w$Af<1b9)sT|jARyzh>f_NMSH_FoWL$060gUbM8&|t#mTn0 z+(4VXx9kx_$;xyxal$dJSsBbxOIsv4g2aJ!5;b z(^J|VF1RNZ8po5r`KNJ1*a*e5@8UcjJb2aU#@h!I-JcVcdE*`Y%nHxYBX2BxC{fYJ zHWXea&d}L_C1|Xyhn@**hd&ml^|Dmv#+$H@B5nq`bx%yjwQuF zIV-HmKoV;*c->iP4wXhaINJ*k33cH7j>Y55nRK>ZDmZ?5g~Td|2KL(kHb+93mh#*| z%ohtwVpqaQwBZk`h1AgG9;ihg9Vhr&iQx(+?w@dlSpnclGYV5(g@LYtIW}S9O`x@g zS_j;Vz$Y7Q82^8q#KoX+|!3ss)6`LNARP?{jEq_{1 z2pkwY5ZTiWQcv4HJDz?aWtd`CX+T+R;G%iBlJ#)){=&prRBxiX#0%@#Kd;!g(se#V z{$oAU;(x_y(Yda3 zlsupS1(y&10hz!#;k4;~rDxZaWCkK01EG~Aj~TFL4&-1C{3^f(5YHO`&fp1ebdMLr z^~_LX7C)%MJYH3HRdMt#Zp!D2Vh z3~J@}t3ngC#k8$q9_y-Ywx|{zdY$N)NISX%dn(wfW$g#lPC@)lFm*GqCr)680^pAq zafR{LW!h%*2O9c#5+sQYfFpP|vyb`MJzdATHyVu{ax}Ijckoe1Wa-qe10fn}{V+A| zoEKUL9kLwm8Kt?Y=(V^b{ET#ewDG9|y&jnBgS478xIg+^JzF!o1ybAz{=^ACC;&_* zBu7JAuvIO9jww!oTfpQT(Y|d=&MHpm{vdo>31;jjmTl8w&2eB9t}H^S#gJCG)X?)Z zz4-SQ&m=xE!Ohcg&amhwWBbUUj$q9kzHT|$2cc zv)*s2ini5I;uw=SzMxe^Mk*ua9RgOD0?&?tK3VW3qi`lbfih?SO>+SEm>ux_8-X3NQm=3fC8EAdndB=C7D5&7q@_yyyG*OQ+drK z?B@D=C)1{L8;&6!=715sVzYQb;hX}W&pEk&fILC^#=Ap5-3VR?6F#5;3SU?`{ZQ}@ z0W?j)?;+5~)Ay!$2&yjy@Wctq|Go|9;^Z4K-PHP6<(UAzM@@dVXP@;qc9x|y!Dq#8 zj?dEK2IT>l8+%YVPI-gG|V4sphto5UZw~c>qONw zhyP%;TQA?Y&KZGyp6MRe{RH8e*z5uGMzJ?Wxj~6Ipya8AY1Lm_^8w~+fGvu5`y9hK zw+)iB>2A0hbz^SRZrF~pg>T#R%KirbM=$%u&oJ%*1prWu`~T3(%Gev4{4X#3-+I~D zlwEmbL4>iB-`4fZP`!(44c}@Aa;2{y=s_g{MioK<27|%J9Bi(4UTa%=s4;!-=goZY zHIZa&WPBBK--@Ff#-dHz%KB#Q%pbXL)0cYwpP%=r0Ca;_G=KJ-;4g!zw{(tjOERYi!>Qmq14rt;>blJE~Ki8uW_sboV*^3u}4UCY?KNPaW^iHPIc@4d0K^y{@H?Fm#Ao+pa8}ss_OpxHO6jPFDFYk(W`%^k=doRB?GtjUx^rsDDsa?m34Xo6d}q}etDP&* z^a4jxYXX*}_AdnH+AZsle275gWL7II2i}NR91XSzzq1EuD2sFTY7nD0qc^%1jKK?p z$_Wu>fC_g6Ul&w?<_#xKB6d)5P;oqJOnHJtx^YV`Cq9|SbCim3jN?eby(7t!yIoQP z#eNM=i|tWYbf%qD*x@8)y2ZsO)#J)h2qG~}*py00wn`|0VT#Z4f|1Av;0&E{3qJj8 z*&>->$W;rtVEzHL!W#|vQw&}-5Ybhck`rxIHzP-t_&{csC%Pc2 z`X<4|G_FlL-tnGjVv^uq;fW8d6onTFd6G(?iCIz%(pdmDF-fqi@W2aJLZf#vBH?_7 z{*R(eDi|3S{JX&%|8FfEivRltQ^nK4RK(QT*vayrXH@>JEL%0K4RF+5`OMu*6V-?( zR;SVq!;98et=vgT+YX1*YDE%pHycT?r5lO4<(RZ$k6P8MP4P$Fgrp%rv3{4)f=W@u z-$qDbSLBLRW3bynRTh$@u!W*wSwKr#o&~ol;4u;&b2B$LH+K_jO6`yBbUNQ;I`=tW zdv1RnSm$>Nh+J@9mkYkP<-09P`*~%4mm<~gCT{dkUhbN_*1`PH4f&7X<}-b!3++B6 zOa0Ie{ZKsi4<3K0J_5hm0papS-UWAqj>S0lz znc69NMCPwX20ittbg)zROv_`#roK@bHtFo6`u&!nSG|+cBh7CczqB&kq#9zq-?q|Z z4rAhXg({HKJ1p1IyEtKkqu8RGD;Ol)$9!J0-P%8qyHySPPFTV?h%PCk^G zdXKjxZ>f{v!nzn7^kCuJS&1*tyEMBml_zy68zGaG8Pe02kuGgeKC8$xs&cJhC@B|Q)a_^*i8W=(lanh$3Si5;Y+BD{QcxqWY2Uo# zeRZGta6SZf&|oPWdvv6&Eq{+YPdt3bK*l$@CpQ!1Eg-#J2^>tNg`!x`W2!|zoAUvI=`p@T0Y6JsTL=(hz7wd+?hB5j+#wAj(M)?;bB zSfE2I_O2nv3mY%0q!{wqsR_>bBoX7)qh(o{kXk|W`W1!X<@LF`TCsg$S9$_;x^O=N zkKI1S)>@YV%^fIVjk9y&^_!8i>4pN8cG~92go?%5G$j9=^Tl8wT1KUhjy$~dxfNuK zKBXt6kTuDQ7ead3ion^q%|r`dqU4LX@|n(bwhivg4ul43mE({P-0)LK&n^C+5@anJ zV7}iMeCcobdaQ6jP?xK;m#xPieu4&dELO(GoL|pYlD0zf7m^sgGoZR>oDnecL=!Fh zPby67M2rxT5k(OV$>%6J@mo3tY9-{dNRsqdrT9hd5fZ&SY1KO%!2v$wkRqLqaGvaJ zR2I7?G+;euPp9tN8U7E73N5HR1-DP9oAVPzn<;rjSy3{1^U2;<9aoO7tDY}h6>*M3 zIjS7TTU1@@98QyAN$GAUK)9VLCUX50(iwPU8z_9Cl9O2~RuhgxYX+YSZz6*8wG}kK zs8M&?edo;RDP^by&e3(_TSIlQmp$iAfC^BvDxqUXL zZ3)I~Us?1}$FAeDV2!D&7qHW&yMM?AF4}OGyKAx#t>uSZoLipxL1&XhgQ0K`@fxCz zS9N@s>E5YmMT-Nt^j6n%usR!$BPufXCoacJ5D5tZ9h!(u)2Jj(;;OJg5mREgS>x`a>1EjX4P zIkS50O>7Uo>MhR~krXd}oEe6;SM;QMtMo9*vtci5}VZ=$3w*)iQOXvbK^2e7vl(rTV4r1Tk%|)-8&kBBt^Ua4W>9 z>`ZhkB&zhqx>s+_0aL+GK9`>^QQhqKa!{euKAIriihF^-+oCH=7AvM+mwBW31xuNG z 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 z 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 @S*G{ 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ⅇhOr2 zzV^AnRJQh+Z$e&Bzm&mRrv1(aANq=R2J>ub{QJCW1ECb>W(v81jXgBI6?(W|;J_qx zWicX~S#iorW(r2^{~|v68hMUoQacoZE*Crq!jP0D166UCF8&9sx**IuRG4wt-!P_? zV@lEI;d*>TI8C4C-TKzu?2Ln>Ll5q7hgZ@UE)p#!Oey%-y4!D`$Nf}_{=b=zG&Pt7 z{QmLt=Icd7E^QEJEG<6}a9W(s9n=ug(9zL-A=oko(65GRco9vCdh&QC&L;524DG5p zxmb>|vpU-cJ_Tj}^bXmO-xtRT7LA{ZNqTN!o4aravzfD}0w8-=b;Ed-9n=mb8>Li|$<1g@K<+?!grcY3bDbq>!y{92d^>q)Ursj5w#;jvj8_XVwLm;I#p z_;tX|(o{gZVO9O=0(QIHr(3ns2!&FGs#6*Wj$gZrlkw`G(gJ1&;m~vbn^3mZ`w7Q= z$H|p;d2edk8e#*67}NwatWbpK%8P}&l_Sj6v=L1qe*>;SdZnE?2PG4_ib#uzi|Glq zjVKY?fTxS2RlT!?Xo!>1(U(+@+%H=+zCmonCAKH8W|`c9Sm-8-ur)}UE#NAuE3s@F zKEmSl0yZ52L*Fw9o7D%&wZFNE0{Al85?%xsT(;rK*Bd_b6WMV{%XayVs8VdZ%#Vy$q|6Z1j}&o z+1E$*NV?JQ3QTw&byZ5~sE|Gn5kra-R-q%uj)EP_i2DOz(aIPjvn?Xbf&^K9>Z2%$ zfO7!)?X3`hl!^kJcHM1HCi?S$RjF(+g<*wli!?ykHDQQ ze3l+(_af-36hO>2CPFzS)sGsx|MO^)6>+;rzl&9d2%x8>KyN)gJCZ@-53Nbtrls9` z(p8n>u)f+fOy9CfovGQwgqYU;#j()e+&07hLn*#f3O5=6Pp4fMR%h=(<4Bwl0~;SDIIZimsxHM& z31X*9I}uqNG`P2NMNDP)i7C;4F*Pw8A4_q}!uUu*s?)%gO4l`sa)|H00oPcc$>_=} zA^Y6TPto>{O$GIDyJC=`LzihsCxqNq$md6P5Tx2A{@H?pxaNY4egr^3J-o(p5 z(gb52$FQ$QN3A&>EfmOp=la{?`wB@QXJLiUl8 z2H8GAq`?MR@U`#PnGq|(PaR->LD#v--)Z%sWpTvRMc{k4%bq5Nw{ui-!E)o_Fn6%u z)kUX?$ImK6~uSn z!?A4m?)qL3DhY$`Gw$lbBaLWfA$^(%N;oUMxAL5In~^EmLA1XN4-4iS$9t#n=_rbic?;~ zS?^mu3tc~D&1^M=u$Y!{Zp4|a7f5SJhZo{$#U8n@*%EWu;8*9pJXl&tEN9FYua&ii z?@E?6VQUPp1T3@ zN#n}sg=@YYhx^R4*fFyoT}vF+6Is+f?Apk++IVgwSxZ)?v&V~F(3zVI*@4Ak53%u8 z>qkFG%Fl=LGfhhWg69Z^e>9o-O|jtfASAMmj9JQ@YmbhrK8wM_7voTC=x?@OoikJR zpaE0%WIj-RjfQ+~zpf#=AW};|kf7l)Fzs$CQkOzl_?i~vNR6)=yEtVFNu=U#F8hj} z;rrJB?metr;{#E2P0}9x6&Sf%#vJ8yRAo<1JECKc2-lxCW^39ijma~jtm1T_EkAJx z<^UjdUS|D3IrZcXH)ANBY`C@@m2&Vhq{!GcY3z>FXvu_Y&yLj4bmDrXqf}M?01!T~ zA(-_*Q5Q9RGbNXrU@vGX9+L@Mnk`3M8*zYb`M|p=PwI zsZLnk%Mc&AbVhl?FjNR-XJxz$84eX2q~I<4N>F@^*)!0~R~8wHYkuCv<2*>|pTU5itzTL6l3 zMcmO)?o`+3Cm$u{%;b|F&%uHqHE6yVieR5iSL7;5R{?cE<^aMSnLqM(48%a^TqLq* zrP0Fy18^dwA#XsTCHdm5vc2Gp19v0v*#%n$|En}}FPNV62`h>X-H>7Y*%6*&H=k0@ zNOIJi55WnA0(qS}ASzyU^j|Ejza5h`vE?u7ac`&>Q>c0VMzX1QP&k#tp~q}cTv)d^ zIKm-1N!T%T`U4A=wSa+t@JjI1Hvl~}Y^cG7Sv8g>*N#O~t}b{5EQZRB#2&-E{rsOH z6H;Ss!+m3WZMtlQ-628lB6hk;M9${E42Fx^SCYSRPTzjQ@e08rbmJGcVS8Ra*614cMRmurAQ<|DUo;w2f2ok&Xv0~vAhFr<*mCQT zMrv#3--tc!-`xQ^0wb##w8r6 zTNx)?7aa{!SU5+G{+RVD$RQVC+z1OL?)!@2C$*8U+X?Pj7= z@}n97zMeaq=YR2J{A0Nd5>Ma}VyR9NRHPY!K|iW78JqseqGb_#66vaCrffp_O^6c! z>ya5#-O>(dabP2dB*4Ik{eT7T`1KC}qYKM}9dl-SPb{e0W8xqoWU4Fd0{zy{mw(s#^|Ho~FY1Q9MERAEp(bc8~8o42T=FZ)%Iec<%Neh=Bs z@|siI!LcaW#U(+)18?A~gj8`CN~V2|ggc(3JJkUU6R*YRu*fU@;8O_(m(|x}woLZz zQHJV|UCL_rWdHl&&A-SR`%en$H_+f~>u9x5{?QXES!Et^(q|yt;}77BU(o5BTT`tc zciRkN?>jy8W8z!~LeTfd5K2Gy^1A^7mgx6n42$O6uKObYoIwmn`e{b5tpc8PmP1c8)}vjQ;-%tlpt+^bhBB13TsCUZ zWV?5Z3-Ycz!xJ4##~|cc!;#s+7MVQuoSBmqP9x~)k1W3Uc;IMbeEUz1B-GQ09>k`t2wj55WNmUbuxCgaL@7g=G$Jr**^u4i- zz!uxB*VciFpW$EF@nFyuZs2W=MM#{o2N8zX4psfioPMj$BDv&=`H0(R>uJXT2>6!1 z{?|BKNbbUgS<34k;vJ^y`;5M#bnBRGa!R+LGLQ`Ug?4P-tR(doiwdz^3?1Ah&G`?w zTB>vI5L@`@v65*QOu`<;;OGRHf=)IhsMvXK(&V&bBvazlF%#K7({G{?n-e1$}KGSP$&BkI{VNZqx~ zpZ0o31&vtc6j2~~@SBj(bbW%u`Sv+kHuJn=XZyapq;@Qq#|KfEwzw7EpA`qpcYDlt z(VD#^CDA)%7BSo}cE~YYkw7e&C)_?fHhguB1;~cV0*7IWKuU^@%7TQNu!1O-4mM*x za@6oD>X@P8e=9%oY$g({0;rd{c4#|yqG}aflKCmFm1*l$_SXKVS|t^bPen^CPy!wo zpK-&KO|qiJM^BbR!e->ERWJs@8n6Pw=C|NDw+&gQ^ir53;VDfH(4h(29Uu2!lZ2YA z2>?bm?%(|+bb4v|w0XhJ?#3#s<@5WxiqecQh8FE_xyvV3=#q7v~B~;Jl$iO zGes`3e0(!!1Rij&t2^j13Z}zrr@rG%t z?P&L{Rnc{xpj~4=)89$?g)f)0r*Hh*TNPEnj)zyUdx9}Xo^vwv3HHe{S(8K4W1aHa%cu8B??3JBs) z;B+Vbp*X9vJ4TsqAt)24+B(q7ZQ3zufcn&)EbsNp8Jj;R-+aMqX0{UTa#v-fm6++E zxk>Ul<#nm)xwsQ>Jw6d%)d}Z=>5P)RVi96y*Z`ErNx&}+5g4aO@uZ%6si++F*b zsWbl#$&T8uS8|->E5{UJn?@2yeIfUQCrV8ntNN@e%u2gv3Iz#U6!@Cz6E@h1NWux? zQ|`!Y7C1T69qX2ieL^xSVKe^D>CH%h55{u^_8OqvU_;+I;XAk^AHwe*^&V`4+xcx_ zbq3)%K7CMH?S0rcL0DhtDdkrts0l24u=f@N^s=ajpk*Lz zPq*?9Sa1it|2u#EBzaUG77iAxqea~-h2hGy_b-&*KF;(SKR3k3Lxp1?5XEV-o=K_G zr8s)Ft|;3tKZG<_9%5joI~wwrWP%jLHT|JX%fLQV;mcnUUKZr=iy@UZf&%H9)$l8P zehvr;Ec@ZqjBsx#MT-f${&nOM&RKz~MZK9Mh(ik(Ke(4Tpdh(PBvH74=vwTaRg@P7 zJOm|J`HiYVe-GeAky-4kQ<4u+;Xqveby}w|6?|`nm0f}q!f?jCT8fkwt{-868#>4m zRFv5rzgwceQbhFlLLCBUu9zft6%NI#4mbxXp+sL8!E(LH!@C5@aieInVXN zf#a4j;Uo;(h##`AZiCmCSQ}EZvA7LIAeqh;JsHi!*MC0?hF>=epmK;sFEA4-Da*Bv zJTd_s!u246Lq`_(MV0U$X(EZ9Xo;sLqe_ax8M;stONVtbdSFXdIP72ai1d9QmQPhW307A1EH0+SQ9*$I4u)U zFs`jZ7C4hAzgvOsuULd}tbZ+wwPPlA5HYnp%mT@Duw< z553SEh9Zd(dx=QEkF<6UTT*Ts_P`;)M*5CY3(IpKC#BcUfIwZY>*l)%2^ZT^OgWgM zD55*>o!ZQIn^st}a&zGXPfmK}8DZ-@=;kxCk?1?Iv}cWq0u*;>w|lIA2%2;(!v!!Z z3_&VUjqk#3Nl&n3+cr>zq4k=BQpHo}S7fdf(e!7TYoB_5?i=G|@Sz4c))7igHZXjSuZ+ncjo%7eUs!CuPgB7FYC%O~Ip;x&K^EiW;{{70!8br(k)Z9_((4=LH9e4Rf zLzC(^9ox^ZOO}zsZEjPm1ES+tdC+oL!9Dt%dLbOX7YO|8h2dEl*Z1w-A-!4i>%y;{*-Gx z$-8d|*6V?5dZIT%^Q(v3qU|@814G?=9+S7@gdL{BcQ07XzZ3B#-GPz!>cHx5u>B=2 zWyns*#>G~{`WK|^+HUx?@=LxJCV1UWY+f>OENJRES%O79tAZNrsx$@ouwF%~83Hw9%w016znfw8LbVt4wJW*37=}XK;wDbS4|RX2eag5y{Cp zX2O^SqwfBlCRoq>M&MO>$vZq;;n9dCmWE6Jub6oV&O8#d#`EFY3gy;oITnK-!%0W0 zcF;aW*4*6*_D|;QzqyL$a&Syx(!(qNKts!--_gT?^-K+wGkFqun{#>R{gttQel~zq zfnH=%=I$2R<@OK!nwM1s^|3W3JzOe?2YrMd|3vklsR(6a)veV=Un!{o%siD?z zGeXlCO)>?VG4oMI7#VvIjq&(sg*r!JN}1ElSCxOP2NHO%uLS>{BisAs{*VYk}MejpV9#g%*n zoS|-#jvNPt!dWGuN=+gcFXPWxdaEn~7T2VO_g;(0x`lZ5UY%AXHZ_Rqpgd@#d3WYm zdbq8(!JRNOTE1gulB-*67nl1^?Wn{rkZ{J|kF+-V0n0dqgJF-TC>T%(Z)GDcZe4;m zaq48B{4S8*UU!5rVw?Ny+J8;et_wcdSq5fi0Q6206u>~eFC205HioEFBrx(wKibHf9s>wwi7`GCL86|+_HL43{V zhGm=tgtKr3>RGT}&7|%US%^#)PCGU>gq>wmVR6kNSIsRz-}%&j!wd3K3#!K5b(+!P zi8YL=iO6Qm#1zn+qoM=G*1eJmiy<4v4TgyhA_1=?K?8+r@W_$&8FMD4wy!chpRy++ z_}&`Emg27g8qLq3M@i%cAQ`KXfqa7vZQF)n5W!4BBsl|YO|E1;T~t)G^E=qEp>sOV zyD-T@92#_jVG(NhF?tc@s^sCY4m(}Fw83rMpSG7E-5U+=>!Y=7lEs>SB%_l!l3omcFBW1! zk&Xzk?r;%8Bu2DqgA`E{Nk$Y&h7{>NZ_HjRqvYsI*BnOgHw`4EV=RPK;R{4lL@7*( zorpCJEVTl2-QO(T8`jW7#b(aN8Qwk-8)X1q}a|Z?Fwg;j)kH%x_RIzwV z=t<9$Lug3jdX+E|ICkciMUbn}5}U0sVsJ<2tqhA>ki?6?;F=_;7nem7T%jhHIQxt) z1(z6u zel}0+#=BCmHQCUMbVLq;el&KkbI{AbLTBac&B!$4X=bzpRWD_(d0v>cNOvUVRBui( zF8(vrX?|VhSXXcjdid6%;}zd*dE`(I0TiJRRTB(HPJJlIlN)Q#ha)&t!$9TA4yi1O z`_*qC;9kt_z9SP}zx4!TyJJc1hSk(oq%5j(5+-ex`fRt=?*>80rP(CO4eeD(7 zdQmXgsmZVC+y{^bA{tO%r?QWFp!rkcgVfQ)WRUkj!C&SBS!)HoLvVrj^!*j<@Cur{ z{2ivpQix^N*KDBa=Nj;Wi>jIh9>QkfN;kToqKbvL4}@3bElGHD(TR~Ys<>mUOo+j$ z@7S4-99T?@_@<8<>%b!+nkFYXk$qT3$F9fvQ*QzNaymiUjK&hG(+nzwrqT9ZR)`#M2B6JJ;k0;#V34~$1Ak1k_C{QM>;su3zKFny6 z4?*Lk2m&e7#yN5AZ?Tzac@L z&BlX%5Y|=Ld&Xjw+IP`Ga^nXNF2QO4fzLSH~Ofwxh`4OS+I44*y)zMf5^RN zv6*cItb2>)i)KIr$pmNgxM^d>4ziF0hI2H8lg&jJ=)pZ5n))j25c{T(Eiyb1yi8yh2kqOjK*NK>HaQ^ziaKE^!iUeh^e6oG=}MpByJzX?6uop$ z0^+Qlk?38PR<19+PWAS%)!oJ#)H_m(cu&&1UQd)>_4btQ@}(i){p+gei^4;Uuh6Ts zU;KM%>-uY)HB8mff|9X?HN@R673t+)Yk0BiQ`YC3_(NO^lwl;9N3DRdb79NgQN5=D z2keiX5LOaV8#9q%1EGu?3JPjO(pX~FCm1!+Dz{10yS&W=|8eX*}QiA4n1teASEP2aH-vteRRUdVkS zG9#+uD^&qu45k|-f5>?nB&zsT>k0ZBs>-M2{wZIXneAbrQa#-->n_sydt01*itRs9 zlb^;3`@O?DljH`^y{K9c=LLwoYc1-{42Zl#a*O++dcVjjRrVm1o!0iYzf@jvy}PvO z`a!gu+VwZTY{cFk4O|WICVZQUH3PZc%zW0-2jSJUxT-ef2h1c_)XgpHN5R1xhBl#= zn*D`;Q3hZj+RPM{>#oHBxr?*fgQV{E*vTamL}U9j6h7X*PsmDE${4wt$_{!Mtxw9o zM8_Uifx{#aeh=TF_K@_)b0_Yd1Cd5jQ*Oo3-zLp4AWb_l&qBOI3_eSuRQpAVub!jr5%nbEM^Z>sPVo*fDg=2gHY=xanzkN|3a*4hEy374aP04r_Ksmi ztFvDu?pzyz*`TFz`&7JD7N(w7tN`l)591H|2@5d9Fj1yi{`;V6mU{XmeaiE_x|%88 z$O#*V-)|_6_58Z&mb~9H9-?1^{uFSgnjU$_BUmCu^A!hC2+g*rkS4$Po$9QQ#Jf;^ zve4n_`CIqcR|RYxyagCChqKNevjOfnF-|}yv)lH4Ci2eXU<336EwN}L7ZiEiSNAq56$tr*^s(+3hF%r=fsSC^Ka7C zP62n133!vYSUg!c1Mb9HH{-nrnS$U2ORWkA0cTfX9KJ>lF3oU>8 z9aBD25+IU^;BjgB=>YIbsY@{xqmu|=19!0i8zdYVPi%90if5#J(kCZ&aq-8u&b{^B zICp8t(eyhKoNY0Nvok;>h!|8Qi|9Zt38YD`;Q>lx(riuq06|HWD=VOFGYRg6XxbHh9^IxD7ytM%&q%vUUx-Y? zSLgy9o(~{{ODmox{X_l5&)GKWBN(=<#}5SS356uT_9;jiLoUJc5$R~F>ns+(dn44C z`GB1iNjH|7=+gUK7>!|7gVq>@LHKJ?kj16}>+GC1@bmp6d4bN~C=MkS98JwoOzcKw#a)wp8Xp2)Zn(W`572zp>+%?F|S0wiLY13+H42 z4Bx93Cy}{3rjKz&JsHWiJnD?a4}1tr`0^R(&mOhx#~_K`nL%BC4mIpO+pQEnAt!sTQW@9g8&E;Ca>HbZSjWF15_V4HPDnt*S z7XjVu!n&f`j#;I|*07!CT_=M-?(_AOv&6E$sG8zcVIZ}D%qhIwV%!4H>SxG2iuZ$B>%C}fdicZ za*!l_G(rS;(?dngQ9WMI`(( z$6NA-kaN9Opk5U8eKwNY^LuDk+OY*Jt*6FUYJjtHjoApn@96J`TU`XdkG~R%HL_lx z#CS;DMSrFhTxwc5^TpKExcQrE=lj6XZ2u951!l)>tPyAc?Ha(d3vja&Xhl$F&kcFEZfS$jB#ckXOuCTye6$AQEq!31eqqaiB?g{@8 zMr?Yg_JV#)sC!0aYsZiQyc%lvZA^%tZJxctKltAc&R~1mJnO}N1UixDqabuA=LIM0 zK$YDlmAq;Me7w+L88L1yikbmMRQ0d89#=_?>@GckvzT|2h-BY^v$WQnfDkn(EU)W- z>$LWH-f3(jVPc`h&+!*??D`XNGR-NfLE3J*YUCuzrfrvHJDmn?q2)#?QC2**qB5Ul zBjlBJ&lTsI2pO6`;8Ekutcw$WG9FA)Lr>m^l74^-rK&q%SOWqi|CR_`;o#i~g3a59 z%)`Ix69YnWM$l`a@1oi>zHe((iMlaq`32d66Xb%7(Jy-Fx!Bn}1{)7v%i@_D2uQC# z9Nd3Nf0SUpR5~5i^U|2qnm*4gj|l;HaihK;izI{a2Rm+v`#8Yn_0UNsQjmF8bB}55 z(MD~7eU%K@wt+>|ly$87WJQhm`gnKJ8Ebou*}Q5itn-jqsQbLZ!5pmv%OpWdJljRx zG|V^WkGKOAR+G*2bAm#z1 zczaV3v#ywUIUKbTLnaJKLTf?JVt^~$!tyB5^G*bsM=(q z-GqAt+<2`)b#^9NMY(o$xSl5Al-pEtyC4|Ts7kv<-G`hxXA<9pHA5Dr!sl0)^0aF0 zKl)~8$qhE7D2xd637(=hJ8rDJtiJE})#|9}H?+EAI4w53FE#4CG?`43Y`D}K%#~i) ztq)YHO>XJ^cvFWW!EOh>`(ukGc)yZ!9Mp}BG~h7nX=`;vRG<@8s#D!6V@BV+GppRMV6>Z$1?M=}4+xlY*hixLWUUi$^v|M> z?=yLG`UHd-?Z1*kY;{-^6y&nhGNoOu=4n)&$W%b&8PAW$K|OxM_yXzro?38wRWt?M z6SVIJxBQED1M-S!Nk2$VXop8BPwv13gGUuDk5Sg`2?TA5k$O0_CBOfLUqoGe33Q=e z&sUK=VKaSUR(POX0<$IYhYepUJsCZTt6uc5I}7+`N>GQ z@f{4rfVmLY&@`_I>vR>}kT_vedCZ?%FPx4;?W#-#DlG~{6$?w51g|o=49>_ugnE7O zB^k^wZK>9)(sr9wkT45ETbVhD+InjdMB&VDA5~nK*n*@e;7tYbv%;&4&RIw(U0(tb zG|Z(cmqq^9@2!5l|FKBK^PdiYf{TrjspJ1~7;;o~6w!q-K1!=M8)|gNs{;f5$6al- zn)j-yuhFFB1E7-udHCz~^tR?>{}%HvKj1!tDYc_1Kfd`TU(2-`k*cE;J!EA#Jx_C) z&v?InJk$B3rOMwK*C3bKZw*4~E;85lEyu6y0NYGRgW3_`JQ=JsnRjs8taspo4sWG4 zlbSb)s}^xILrA&~q!l+!rPfm3uo#d7e;WYHJyoh&GxKL@!M1W3*!q|%!Mc!!8GXrn`ITV>CXYr56(Wk9;iMFNo@Jj2ve-U^!SXdgN0u*pR?m=*0C~vdN!hNUD>5TX zn64@UQ*qm;@VFYwIWvU5MjJR7ACMRV(rmIP7{Ic%Xp7Lnn%?6ac)H~H*UI0+SdIf* zYg-Ua0q^!*sO*mD-4ysH-c#R5W##<5w;d6yOl~89Vcf+x%)E#~+oEPtT<-Oo$@OD~ zfG{ptyC?$Gl8IR%CK`;~6bO3D++w$2Xq*1?>fTVMA_KFv_qWmDgsL zNBFP56U-605b3TQTIVGo7R@Yy6rT!ToXAnk4cFKNCu(6d34)hTUa>a$4PEc1Rm!zt zV)_A^TxBNw2|W=M;*3`z(h!4=I}aI_ZMV+6+(X>x6W(35Hate^W21Q)8!XpH%ny+i zTA!ydkX|}}e8L{&G3hGC`oWW&|9%wMi{jJBWB(h;62WHh3UTPN3`Cm3*S)zF^)<1>v*Zv)D_<9#!G28gA4i zQT+KZLP-&$=!F(Jddk5J&iKVNNl>%w2ttg0;h+I04%~YpGKE&Em*wCg$x1|@U$m^@ zbP+n-4}TX}kjBZn-U3pU?C>$A?xh1FpKyevj<>vntl zz9CL+#`P2Cs!Y0o11k)Kd3&swM|6^XfojzYqmkKvh2rX}6#+EN>1ntow{3l-ke^^d z8|pGAdSi`pCJ0-kgMC+;VmzX+o&SK#AHoco_-{6j_sJ6(um`Ptl3ky(dGlYfX-`Tu zv91kn=uHKeY-+}+(>d-7*gS=bRt)YUONWcQM z*T*ZVR0};?jr)`s)4Suq(KPsexSCnpUD`1hZG{9TAN>oi|GG_eZg(0|5s9r z@&94|{0~%18`fQS$wT1NqL?Zs*F;wTs?NO+JS)LujULLx_=?M;|AU ziONQX*GL}h1CPR-B`N{~#zoRJB#buPHyccWvfLz}6(7QGxxiT>FRC-Hl6<@UXjYt% zizTSyx82$C`S`Zc{&;pvm&fn()dcHC3I_Jg2ln?B`uiJuaO*W&^}8;pXLg;b`5|`M zx1`x`cDPlFIyrv-pnFRrNAhxLMxK3XE~OPqL5lq!YW^y zHcrASDr6{&)O=8fqL5ONici?@$Ri@e1}kHx#mW~9l~EK!#*k4-T8S~G47YQFvOL}y zKbdAsA914TB4u@@55u4W8UyF#p5$>MsY(msHB9i0T^btEa_rpWAqnQxvL1^d$&Pb# zIUt8r)$1Rk(ov~JoQ^olrXX?N(UVQpc9en9G0E^fIz3i<&&Codqi;0{p`c^XqNu|| zhox#}C6q7AY3g~+~Ba!&&Rn)6{#S?TxQGWVS`ds1=P+1tT^v-A?f%+K#Q;uqH@>jmbe2y4dT ztT=9kRu+7JyY9!x33#2Hvz@~tb#P?|StkIkQ+Z0+^7IYEh=|)bL2a>X)G#$Bs_#Hq zZUzCpteizCapH1onHI@?ydrkA4SjRwMvhcM3hJ=cMvfmP|N2baLP4?kL=0pk;$CRD zPND7d-8n1xmqxRn5h7FfQo?khkh#N&_Vqv2+883y>kh9th9)XXD45-N5x3>v2;&25ELsgb zeZ|htrX_|74Zl$(-bM*+;$puvP#jtF28H3yFv@1qTOKJ7S&VtCH(%decM1d;z?4+j zEZ){%UhnWQaK%`qxN_tC?muM~#y_)f5%b!!6~i`DgYIMLMyMN*Hko&c(POOsFQmP5 za31W|HQvUy+1PfY#!h25wrw<4W81c!#_w>?(l$vScR>VXX@q7u{)}`wsjjA<7KV3Hxhq+A zIxd1v5f@1lIVo+Z$I}Sv z%@Z1FzS(BcK#E0Q1>zIO+b`P&=bDR2^u^=pV4TKESS*qxM5U41XD`?`Y4AcrwQkm6tICk=>o$~(FvHSC(s-eSFKl-TT%E!9-$kH~D%?S|9Ss}VFN#)ktuWO)3_q{Thz5kf!do-EgVu`&H{(}qf%q!j- z+D(p>CL^gM{lXRMV=)c<(7d@z5dP7t!~4knZf0w&>i)ODm(snKX49y5rS@~`_YXLp z{`V2bh)&L(Czp35cHs`8`yVZsBS?<1=3%q8s#_CcGr8V3wk;ega~NVgD5OI2u&?k- zT6M3R)L0kJc~m&lB**Yru07zdWwnYlj@#v^8m%8V>!Ndp19>;l9?$9bkjLKP4szuN zQ5wW8?%ROjFj?V&9H_o=%-#02%^#eEAbu5E+fbsjGTja3Y1DaLqz*|en`BqaVEt+0 z+(9cVuz%|o0TK5t{=S&i3WrR5cp+sqjkWo!_b_kHR0`?YfKIx6q>xE}o52|7_FI~V zOZh{ojG`!Hj?iO!6a&XRuPE4fMju>2Z>dc_!V5@ltnK=(H1iprn_b_ss&XwEa*{E1 z6puiLC1~1FPtL24wthn9ojfS-G}ETWkwMf(qfJJ;=lPt^86F|mAowN-L&6SH(tX!s zyPIIKno}R+scVs9eW{$bB1e!Sn6Ba+jraA#SwnPDxC$W_TWgPF)m0?+Q=E(b7I$o@ z9*1d4I$L@k*KSVPq&@U$-np0jPR=MrZmP(B6Kz8ccFX8isS{`!59Z5aQsJj1K5WUo za;mMtyHnrs8p8XeVlPgcag@#g8=Nr+JV={q41$wa#FFXZvqe4s7S0CiH`17lU5)Lv zFg2!@n{#$}CgcEn2sG)P3yf-?F0K2Tiyrf{`;j;KmgDInJvcbEB8IH{JiedByUsIk zjwl6fDd~XiM%#mF=~6#C^@mwNp-FWoSKODb#~>G{?~Nbi)eI1#mwJwD&r?gwH0D=U zCaOE@f{hSfuaW5*--_XW1|RK^lrN5y34aV5S`wgd;rL3|2wi?LO0_=v#!KFDeoJqv z@wo0O!oZG}1r7NjuW*J}t5T`RtCQXU-Z9a(fCBg_5PG^DNSXhFWBT5uzM>1=_OxWN z-EiQc&Ri?-Sn3sQ#dvPrFGW=?)ehQn_dfJHO6CXulQ!}x_+W*5LWH72A->#t_)bj} zQ`H&hP@&6E@>xS0I`LYV+iH&wj_SNauCilC#7boM+593@ZVV)ZZHZWr@?*7RjY1y* z{0DFMg;oHeARDBhst#wm3W%u+Nkj+Lv(HAiC_K7ZTw6i+v4F6}Elg*%wVdw8uCJ5!! z%u`r|Uv-Zp5_<`)KTIzRKG_U-jzD~>hS#C2M^}8dE*v}R*169)`2c5C!j+BBl)+M` zs)nuLMtTZYx_vL{XM?t<%Z(=2bOe-GwhXtmjOH%nLj%s`ZSa5Q=SLJ&UD}xI6@g4UA(P|O#=8!@Yv$FCQlGu^fOr(Lwj$0sf|+9 zE9EXN6W+ZhafN$59?pCQ>XN#XZiXn+BMh5)#g^kz&zZ*S{)xG;L7JKRm?g_zogfCZ z1}5?CA49alx<2I+Q&I^Na1?#2$%BbHKDQWDl1_C)y*sxLpYihd(xIvHsj+k;zrQsN zkG6M|oj^0Z4V660w7^5-<(tDjR<{hflv(u^ShKS-c#FJXMe7l(o8i6>=9YCawgL!u}DrjSCCxw5c zZhG%qs(}v!ey>-AFalGSMkrWa+D?x|n~Qx1_hLww+_M zX1IFgN@aelBjizqMs+MfxT))4*w{1RdJU;ZMc*&E#z73 zr?Y4TM+wX`rm+)JviU7*E*}w-&;l93X>LijwXn}GnC*k@+(8@a&ObV@dGa@wacJ_1 zu_J2o-)A>uUO3)-I&YwS_vtVV`Ocb9o*T1eJkns1=T_(+!_oQ6SI8*l)7H%#XFI6N zG;lCJd4s|@-I^?p+kRQybwF+WhL-+$4_QHF!D`b48l0zR1iqtgTH6H~@}%VqgZ_(z zA!y-#Mpm6SpbETBlW$eTwDOF?)M7Kx- zf$Vd{n8*&D6%z{&`mUs~*MK#syG(7@W+_r2$h~} zl-e9V950*JmB5$j43{EK>I(3VmD4E=Z0bhHJypuG>AS!Uw@u}{bUfTd7NR(v+X+Qk zhxQUE@7J&3P4lB@O$AE5vX2MN3VV2%G|r4daGJYeBF-fzh#5p#V`9=&J8jIDcU;5j zXl=m5jPGLa^8**Gu_iA=m5k`?xio6j*hHhDpLPQlRe~wI)|SoPP^>X-8F<+7E`4i_ z(a4PHj^WOPuG`DA6l&y`Z;%U(yOk&09I|eTwsa1mxQA;!I-AhB;B0>YM}Fz&I_^ZK z5%ekDS!7Kq5TZG>AwkaZ7fjMY((D6iO)hFk8N4qPi|kLFST~I33U^90{i#>o)-U)R zRCEW~-tFfpXMV$&^{fx~v@6I(Qc$Vk{W=v?U_b>YinJbwk{)GdBV*ZHQ;j`7*!Gal z6?8tl?W~#J1#OE!Hw5i0w$=l`)8MSSX7C8!id5JE56pC7s*R=zJ<@&b{kav99nA_% zX|wDLvM0*Im$FzBGQV38SVfj(= z_VHJbcSTrFf1qPEpe<{R)t45sjn)s|7Z}0%g6i`a1Lj;(h*330y-Fltd@MkX*O9te zay_;%fALx8IBy#kOReIES+N%XMX)LI@+ga@KEBpA=v{m~@PRoIgT*dg-#Y7C{XLO1 zo?HM#vp(y^mG()qQ*K7(t-R$06P`4$2&|`f%!NeXIcIDC+fWamACvS}))m;Az6IK> zCp0gkU<0X>o{I0!eBPCujy8Fd@pWe>2y9S){G5S_$3cM^`-&&8;q?fq({pEMit?8D_`kO@Tq23s@gjWq5KZP;HSVW(zdpS^fXMWR1Y%OR6gCzjiC5K%3*wsS8QjbsB6^QO_{UG$5ZX^6 zPJS_DTT7i^d|8T&WR?YDA9citvMbb<~Z6!(PVa&o{6n&cYz4p#ys@uT99t zW{`)Ij0gi+zI>4|j8;cQKJu>0dZ&Jh!Z)*_>nE4W*UY_LMs|LgiGha{u|Qa9|DlJN z-|((a;B3KE$?cLYEL=xHb|;+8wYPzI_m2C$l0%57jAia84;MUXs7hcr9XLeEz^7sE z{utl{#ITd5F{Ww#vCZ`5MGtV;=`=27Is;`DRRM2VhgN@36mOKc%EUFwg5*5>U#1bb z7HJ9#z%)7m{QMtp{l8lkSpRoq?5)fUEbZukf7_RUfB67#FMogipHKR4`|=+;g@1h# zpSg*Sox-nA{g?HWC;!b1V9RsIm{*H6GgwF#PkQE>U|mld(s(HJOi_X?$%#TfuuBCr z8n$2?vgN%&yoZL!$xMiJ;^(a;fl#s}`&5pkHZcL#v5$|rzh53gf5$a1i2O3x;|jEk zLbxE>B}fuX!bLC3BC8jaX6HnVQ4L=4z|rvS?Do`=9Jk^}6(F_l4GpQ{%HKHzd}k z1etcBqy)|r@FwV8`SHbupbk<73_q=a;tw5%06=5hx$Sb%o^xlllK}syd8wc|7)&6W zu4`mWQii_Z00}q7%knCukbK=C-OpCZkX_4swahUu^7o7?ardGB_bS^p;=5%(JI%WpHfBSbB{_d3hJr3n2rGLd?&8p*a zv$(7*H02Z;wa@~>HnQIrami!_E%B$F;R)%byyZoGM~N-1qNvD=4e$rq0L~h0fy`Vf z=OhlJbME^UPPg~BmM7p1B2yv#D!K1r^Ptq5VZIG;N|@FAT!|0?1*c4&V{PAuz2}4D z=)m1znmn|gE@gRXg=JD@(Y??AtwJsV|rs!mpqA#_hXpwEp zXGuSpXeUFuaUIz1nx%WzZfD^$v}P!=!-?<xZ$F5YI~f7(vMAVHtVzCLPv1_j#`O^QPc! zkC7IqU z9`}SD@({vU&KIMo1-32LRm<(}I}#PWW1zXOTWENbkAB%5SQJz}CDy?#(e7ONN_L-H1bPQNK;d_49;;OPI6VR&`HZnU)gFM zi|b@q_Zc;(zU3|;&3f3VwEtc=VFc-M-Uc}0dj9B*)BG_i_|2{K%!DlU{}vZv(aYk1 zvJ>#07n8%9c4BPAFHRMEFcl;Y4OW_x{aj{go@@hl_k+($aTVm-%?ECUT0=8FghP$e zYxiTVN?xAzwU0QuG|<4%n38&vJ<-8j1P(h7()N<63z|$95y`USd(eUNa9}JIURAHDje57 z@or}gR$H~=1Ab95vaJ!741x%qv7RlwDW?OXOegih2K-&+$kfaCdBrY-FeJwdv~LB1 z@82qqe~fB^bI(Sjhqs?3^jx($BcSy~R#*Bcc8vu!Tyh9FBG(6$5as@?^6Mhs-}oTr ziE^3np?7F8IdxIvYc-qG{hb!yxa+4;)?qxA{Z3eY_N9{u8xIXVNtHxxQ5-2-6ukm^ z&W`xSe(r71-~xO@@%fNsquXa-O(46aF`@z|WL`~RCbCDmUkN=E0?eijfNmC$)c;&p z{$ZEoUkUveboRC`{{h}N2_Qa{fc42yspaYso|9n+$WfVW2_i}wl}byba}iwgWe0S_ z`3|q&=m9^;PA17h5mvXc+wE~1WnAMW-bc){edu41?(8r{3RPjMvLx(}WVdlA`)t5Y z#|pey5&qCo62Rl+Kjs(fU8-q!IF}DF!-qIG%Qvi~<2U+a5>uP&hGyNI zzZ&OJTw~tla}xWmYX@|B#djfY-LTJ~1IwRLB-_`BMNFIE#lmZKq}z8>_oAeAz_IK_ z<(fOK2tTFvC05dZMTn!3$*(k_{#uFpS#i`^_~bG)X+ll*y41#_E0myQ8;a4DHAlo; z`;ht`@)w4t0_=K501ST(Mf@{{tp9uZN$FVsS|ucJuVZWfHz?zxrM`CkS}No%4qEb1 z78JtJ_Z{nUyO4phCl}Ir(pgK}w=R!mS$FHF933g%%f~nJZF2%m;%x4bu~sIJyEOg3 zQjr80_}WBLw-Zp0a0nbu0IA5&PBjNKOUoM)t_BwQakhf-o!F ztPCG6+DhB_=;a-{x0-8uvbwDqv@_yaIrIWxC;<)=2Dc|z~65DGL|UZA2QexOPPX2aFFn*(V(ew)XFF1Kl4|~l3a6bMK&VQiue@{ty z0~-eeOFe`Cfv4QCbQhpu4IC$4mi-_o`-1>%<_mxW*AK|0v8>Xe!CrZm zk{Z88!!D&IRvx|>+2HT5aon$rw6^_h1uE2C{vJ?Aj8;{yCm<3)U}N6mXx(M4WbA4y z)4oqsaMI#V-X$t}ICw>p(7hCETh*O8+t#iv%3`6c5hn7DV7c`eA==WF`^>(vR*~mp z-Nw=#X7M^A_?k?k=i|zyYj=DjE_4H#+Q$SwbyQOrF)agAMghwZX0UIKuZ8m%K|$R| z#|!#Fs<2?ww%-Vj;qE>7Lhhh@wV3@Iu9bX^!{XWExovbx9IAPPXjU&cEp@>lk<|wn z72ewD%GibAyVvY{Z{W1R>380%sVRe|_hrez^6LpomTv_hhiWlG|Y zl*jYfeKQk@k)L>KJNH3J8x0m`bsEHwGhT#D&6#-~fL~<$0HlfJlyo8?iIeGm#qKOA z?e%qkpYFrgOLAyj`09nuZkQ?ZK^-<RHkEJv8h~KqAI=w>! zwwN+8UDIqzd=5ATb;Ynh3-4N4Nqn|zW168-zV!6pc%67-0qWEE63-YrFeWMzM=;5u zPye}mSZKM*kV)Djew!ml8ntu zq_cWS2GOF7>^9C4x}s5BA8awyiQF#Z?1BIuYH1FDSzuXC4AxYlouYq06|>AI988y) zlqy9m`C%zbd|SHhnA@MLx>sPj9{KVT!CuCiL5@Tu86=8vmWcs8N9&_rwE?>l+A#`I z>LGMQc&80lBD4TfKkJO|WHL6jNcvdqAoKE@#kYt^9I^wVkqNNM@t+IEKg=@x6_J7_ zwg!6kCXNPwD->ml$Ck({jH?jjdVYUq8JL(m)tFz78UMFqk-+stUkizThI6S1Pg(6?_&E9D7%fY zHBE0?E*Ay1+b=W06iKZeMqL`~pZHgA&*&pWQ^+S+Bm{D2jOYRHEeh-9^E*w|OvUN= zXC>l$=blr2Wt8TqL(c9_x6RKXQ^%&NYeydtpRzddkt#Gh6 z*NkyeYNVUxP{P_I!lXyJ2Zn2N*aREPz7b-IP07w0qdfSu<5`Hqn2OyM)QMtA)y&zR z(lKqB;b*6P{+fzc9@yH{-qV7`hkltJ{7l+z9`V zlzldMYjtvxvF#T73Q=<-7pP&8UO9Ju>X* zCUOx|v0r6aiuy%|ikf}e*~@TqY@}mA`^9+plAY|OCwY{qzhW$F_fm~Vk+<5VZFV~{dFgc&0&%CjTJtQ5nGuqd$R@l48bMr!`)%-`eXh`mP6fCQmVPnCEw z578fuT7@n6J_fG7sD{1;?6m~&m}WNqL`2Bg4(_RjvHM_f{`;Jzx*7lF=U9MPg zX!41@(V+(D9Q;@8GJNg;&NsuqO3NLj*?>YZ8C4&x7T9c0VPC+N-M0LRJ+6`jlBw>? zV2S6s@KJN)VRdwoztp4!1a9KBjQ!T~C&H6=u<-711=%7j)@SabExXxb>^wv|LzM&in&yh`CF3!(?9G16pSw!2QZ5@gQT?2mDUoPy7XbTmmy_0qMWk*+1^o z@boRxoSpvso_^8+($8$9?F)V_YE#F7q31EBtKpoe8&s6v#JGSt0$&B5DmCsRyak}| zwQ8MLt$bbs655@8)QoqQTY)FqXUzYi@9dNAFu&;g<{$Y1;~(j};9nsA52_apfKe7e z-2p00z2>C*mkOhi1*kA65`YRrIgfCylv?$#F`M{VZ0SS$^zpUOc#M({Mb(YLXfJJX zzZH1@^mP}t1JV(Rz7nq=iIJ35QXjHPzTd%zsY@tpv&eH-^G5(G;A#z~p&Z3m#d1F^ z1*6(f3m@5Q*XT%7_VQM|h|h9$f<^=4&6^Irl{B$A$3?~LK&q%?CqAt@#!*PGcfpx<~;u4>uff zH!%Argy?z4vS^h~#*U~*R^7GUDvO)Nf(MnT#o@K$8HJo%DXJInR2g3-QbOC(V=*`dT7X}qvTfhxC&aHIz#JM*HkMYBv z27NYJz1j+|<=UdGIA2#_!7T_W|ED;#4#4vk%Bwd^*6FYJzEUVeP`q zzM-E%|0usSm>j#P5E0E5N>*^LUD2!)W$wde{UuDbhvG9%gRF-bzzR_z4GK{rms=p7 zLN*U>{mit6;F83s*Bn33W#-PaDO6d03ML1T(ctFVrdV%GsexgSbBU~I6FM0{Zf4;Ys(J_BxZl6u4#!6Pq_oQ!jp*iyl)YRu5 z(G9P>tl)O3qve5+SWQC$``HaS?4^pJez4iE+YU2e-Z{A|-{A^x+_ z0kwLx1&-h_z^OY8E}{OYAQNq6iATT%&1M7E?>NPw-_7`Ha=`Jq?E7$L*#?xrigKE3 z0s)%{hA-{Pnm*ekIx<{I0nso*l_^ZXZZp3U?%A`?4GwC^PjV=${W7dcQnfXewV>v* z5q%?Zn$=4;OYM&gz?=&P^zVmpC!>>H*6dm|0!L)r0&jGzvcj=EVV@D{cm1-Z(}bL3 zt3BOqpP=q=XsP8SWx(!C7y{W9!DCpu68N!j!Qz7j6{!>`mWb!_Ye|Mo^V>dM-Hc*F zSMd)RN$$zFL(FwIdfPv+a^x)@8SMSmDwUF1r^Wy%Z~q7-^B=3@udMvH8S>w0ISfck zfW>U0r)O5HR&lEoMOY?Y(x@PK3FLhwY{P32fR!R`9ZlID*Nmv~@PQ}R*-%X*2xD|B zmFYe8agSGjjaPI1!-+NpI5d;$552j*)G$H;!|?>q)^TeU6TjkbUK^{Kcw%da`AFja z#h!hNMr=AQuD#m0{^{BSZ0;0eZman+39Xosa>jl%cp5gl$G2Z+156OBZh`eDMU@?=DQ zH5DA^C}*``lBNyr6DylSD+|=NX69>9ylmB4Hl0>F5g6gnDhFhq*K?UQe2@cX^($@! z+9xrGypj-?MW=lywV))&`6lz@BwUlL+uExhf$sFN0x0&#frn>Q_~VP?Jh2an!1TI1 z$@%PAgyZ`57&toS$d9>?F^d41*=LN}ZTAGQo1x@MrE|2;3~wrFBymvwm6=B0QqwE| za9;iq&OdvVe~0sbq~^c9%1&|6V{lI*%02{O(^7nqut{yngRV(XS8gZs68Iv&=Bmx%6Q|$P%R0emhmiEt8O&r7Dm! zb+6=~({Z1&X|^RPQOTd>3hyQ(9gC#thxjCr@+r&dDw@**6j&xNRFaB7q&8>$Z5>w8 z!w&jjA;En+WGCW1jkTOR1r*mD^44Q#MGFh_Z;ALRXX4ruBk{L>Xp8@xO_9X)T2kkUIv7r*rrdW=JFdN#8p`KoJnc?ZmGwGH*YtBX7u%~l04 z?B}GeX&r>!)o1tv>mos_Dgx1y{Ym2c4K0pTInJEO19L;YlP2HzWd}w-b4CXi z{9e?Sc^g~blk*P-9UUKn&nY{SfbPL^|JhZMTOTyi*Yy$oQdGV4+2eZ`$dO(fJf_Rl z9{80nd(6+EziQ^vfL!+f?p2ciF*^Y_SO4ZA`2QO~fAKst*_R%=-|plOksp&^B(Ww# z{hooa0q*1?8uDA5E5qdm{Dlan5&DJx0iL0ukzt05Q_VVWhSmq#N~_KeLoBKV#wrWK z@yKR-54L9AMhcc+ZG*=NK-&Nx0vD13Sha26Rwk4pVHrl4`v5Y)eEPPx+js%7x|b8r zz;-lqxQ#WTeCcb9@XbyDOz(S#EIop!N*nTae26K`A^jGkTn+{lgBph9<~?bfl9pid z=8fbDJ#i|S@99H(q(ekt)+fmRyek~UC;LegggI9j;c6<&Z+W~-^2#oIbSr&8a;yNR zV~yfP)GRpC11R;R0mO*=yjvNbsYGJgSjF0_G*FU!8Qyb@&y;6JGFn4+OF`%DV8IqSU4!YN z09-QvuM3p>*Pg{%fE?`nV-Ehgi3?ayWUgcTH{9|R{<`C5-coB0ir7P$FjST|fd+C3 zL^vRn@*z4la$tE%+WNG5`NT4~^~ud0fsmk65MSy=_6YD8KcqRepS|1O$jIXu!1TGF zKc7DTKq?!QjT@nB+^G+Pm7kr>qPd7u$fhF`l{%C&H2Cf`fa(a}gx4wi@%YP%U8E-jP%*lJ){DRPdbQdE*=P2Pa4%N$*X| z6IM0{i}lX24K&9fzYb$rLibZSkJ8)cC1o*~L`H_N!RXBw;TgDB;lgmgr=bPB^*Q9t zd+Ir4RgP6gwlA88m>k1kxY*!bGU;Hns+GiqiTgr6jhWo2nrB-PIwaRRPMSB#{WK2y zF8kapx|Z`T_)bS{J84qdfZ7ej(Px4H*DvxDW)5oOS6ci?kbHN&B?n+RWWK~1*9oe! z?E|7RF;l`?LSWM4k6#Z-`OPR}q{zvPhkoD*4BF!pr9!+5zF-rcFU=w|zYh?1^#|b% zX@JCO77{;;k_L|n4CQC6z)e^}bl)J~?77by-N*sHqs2u{xgA_7#1x{E3#AfUeRQjM zcbK!YwR%6uGmvKxG-oG7OTKbl)k5`ejwt)_W}s3N!ix}NkFpik=!i}~8dP5G0hX9EXi~O*Eq`eDK6}oU}r;-;AtD`XlX+MAoHR%QCw1+GxFJQ@Y`MbAM zV2pxE2rz5{!T)5~{8=Q*+uIuGSo|lC35#AA2XtHeeol^#S`1Is)@DOM*8S?XLjCHt zqMY~Rn9Bo1BCP9gy9WFqE1M|?g0J?h_mR!WbDwkA-NVZrh`l=<6u60auF61nSumZz z=FHX78Nf(QA8lpa_O@kdE*@kK04<&2C7Oh8*B+auVQuCYKuf1iDBOGb2t*R8V7{gg;MbXo^-XvIaOmA1CMO340j)Pa8DEg4?zHqPF2$p z0W)`Nf#hxQ6qZ1_ye!f zJ8bv`{#U(gnO)G+2OOP$)`)*L-2R2%e-oFm=t;n^13(}GoSM~YYML@~etxOnG9MDH z6ub9X4-bIg<_Xq~(l410KOrDwrxY9{dapY+!dtWc2tL-ozs&hv{)9yP6LvpVy`*`{ z0HUr@_%X=7->~kmyzf#DMucfQRRH5iu3UQYH)xj9all47ketn15`tM<4HqWN``n|T zwV*ir;TF`Ka+&aQqin<#4xX$lboPsYsavztFJcUq;QXMtWiyaATFOu2U2iyFLFAiX z56yKy6~MGu5q=F?kn%BTDOU)Ky6_lO3J=Ni8u9Z&KOxmawy?^!+>Oh*A9!(8Z9|9e z>Oumj{7MOOx^@COmi~{M*6kwvSKvu9D*AM(pN8NCy$~bs#{aTuRC&rw@M)5CFnH zM5fS^`dbs`sf?Z;VT{5>g#t>aKmLYDuv0WSp{_lX-Ps8DKF{9R@$xnFci32Hditcm z@FK1N1`FN39%^5k(baHm@_F~gYO9AlGjKesPzZldb!YEy`(>{CL#Qb*i!}XqT^3+f z59nQAdHBV(mI5{Er^^$tV4l*~b8lSD!pXuvClv6{Jr+rj0kgdSXo020H6ROgbv^?* z>?IfM-T9S<{F31Uck3$Hfh zZ}%IRLzKIqyjb22SVq2mDfxVglH>yHfm~&v)zSlVCJmHSC117Uc14Vx^vw>k>jEvk zWp%@&xZy%e#ZMwEn}z&hX+ve`o`Q;Gc(Wu?9O#4fr^{P^3<1|Jk0UG|SW`yV>jnxY z>jZW6?bP{|t`l9SslRm1B9{vf7CZPvgHzByO@IkI_O1W+1$<)t4+;V3pZ#%A>3>Jx z0r23;zh)@?WhYI4&rnJ^#w0GVvd-mOXy}!QQGe?Z=|z`y4^k9`cwiUHUp8TF(Q&Gu zp}TNGp#}x@KzSj*9n;S<2JW)mA4_u^Yce{I$jJB!Xloq5u~83K z?#l_M26M*%Pv)&%cq{!taSw#|q^Z@*c!NJ}7LA8H$RwUVAX8ibbHA+oT(0z4AmF9O zn7@^Z8#AQao)zixdjy*JWFoi#o`lDEh>HU?a=@x4%JUj04|FT>j=T;ds+3ToGw>Pw zl*=dMa#O9#%Nx`T?AlA)gsdItTgIB2wKHm_T=l1<0$X13?J8#i2d`WBXK!IenNC`P z>*!5-SRb}1n7E*fjIdsfL2~`Zx(!<+lkAl!>wO!0N-|yBOvpP*@+^%`mRL-+_xs*T z*P?q@d&0h>im5IT-`TmJ4ek1fX#{vvwxP8zIHqc8)ya6@rJ;WW6w9?rH{9Dd9IPB_ zen0gRxrMg1GMfXvT5pCQlRY@g=zcTSrb5B4q?n89m&#uMG$j=RYpw@fap1==>Pvj%dc@;VllygMN63CqdKxOVDiG7s|%tVf}B?I zBdT>)d0jFgc_z8(@+T}r2hjioDbhrcvbyK?^ODv3wpp7prQ`88*;m)|QQz#{XJXzF zj{WxMv6l1EmKgPSjkb^4uy3>iAIAMIsMDbdQG1{XPWnP$oP$L)l@@X?#Dfk>O10#J z$Xmy5VEuXg*^=7xDwQ`a^3Ta{s9J|_xcxn#&Y51n==|&ol;o8QqI4g*`O)>!|7)UW zF@5F*=JYr!9Ho2bjf6j+e?_8anYHL9cK$jgj?zQ;;XRZHil_Edj!(`7@^l7j0E(y1 zQwhK1CR_ebsvgugZC9mEMfUy~Weg?u@f#n0{!PMZ2`D0{gd|PKt*^i&xJ9`!Ofoam zCLJf2Tx=~YyF0eDy;yEci-N}#WND_OE@KSJDm->0x3*;-Fk#$jDKN2)&Q(#8bKjSu zhkC*tTx@^|q^=j`!HNY>Y=uQ)Gzp`fs$GEVdkD`i8RkQqKC8?njWk!eU-_A3wlX1O zOSEWez8L-}xg0rD*vqZ2&@NvkSxiQmc#Olr(vpfUCKa()x|B|M5hr3G+nw+nB77`8 z&LwGU?dV5-P6bK(_A>@6M^4~bINF7c?Wji-q``1XgB;e$pvIkg*M<#!m{jC?@P`QY zIrmYjwVHf*f-%Wg%BXPqg@yIWmIf+a?aK~k_*ak$DLNAq`D^9^kb1){1#JVXDLbc# zyucOn45rwv=w7q&N^e-H_lj~C*E2_}fbg>QLDEG9PH-+VDH$wj*FpCb?|h0Ew|tfA zjQl;3=vr=~{&Rw)i_{mD_)^pS;>amQ9(ftC;*{iq&w8lgdG?sSQd|bFxuvvL)VS$m z!pj2`D1$!?^emmC8!)1?;>-=UFuY9UNXxg>5WFx8f41ZVZ#P=%!mvpa+r+L3FKot} zZ!bV1yIs)FpNU4u(swm;arK-YLMrObS*_R(o3I~Z%d#f^X zlr$X0F(D?L2tBY4b4;w}5H%3W;b7sxl_5Od?^@bNP~(L)*&6!#t28q)EZnfRZ!k!V z_QGy`?nBVSnkV=GWBicwSz3ef_=N0dbk}?6vnyfP(iC@rUG-*@;{0ZhZ?@%W#cavX z%gU1tu57P)vvu>A1|J}Zu%4OEW)~`KGWuSzayxHhG zys4pxG3$e?m1pjd0;Ou%t9yp08xlafXr}ZPr5p^xEz3$8iDS|X?|l*{Z?L?zS^(mtQ8Q-Rc`c7s*YrAg(Qc5thd=aF#$n|=aaz_mcp>^@}8V6<5}N;l(eE9WCVYLszs zM6qb?jEDm<)(ry{k|NKZU^bfn9c=?fEgR1i*Db16sl@)sgSPNY#G!rioX=Obl2fBZ%CCmMhTY$uh zNsV|%+LYAKhe7-mqkhOv#;z+47|f3I2r|H52_dBIvXE+r=N!%?Zz9BCS*KVy|y?n%Cg>>MoVr^DX+4v5F z)iB2ky?Sj$7A4J?+T)U1hI`@j1p6LclP{=3@O}moT*Fe?s&YHKm=C!=xv8;O2>SMy zkVa-gDI0;R865Tj&c+}v+&vswn9$;8wjG^yw>54w&#p?=pU44m@0Mr+#ie7lDwb*2 zPDq%39-qyo^Ei|8IL$IMd!m(PTnCdgvA+vpB^cjx?*I$#B3laT(JTS5Fi7=w@d=u(y8;m;~32zHYNF148Ll|))9jT+XfEdH? zg8>#Vd1STqY!}OuHx3C6@~dEyh?4iz?7isEw0fZ8GBo@{@iAf@wcw}_)s2yijnSW- zq}@`b2d(O^8oi*^th$-B4JOV}s@>g_AIvClHv--Ikh)nt2e~`pvZc2k48()<8A&c+ zs%g)5Mv{Eq4Mvy>2O_||AG&8$e+9jI_?gE5D(xctnVXi|A%i6BVJ#E`?hUAaQxqg> zdizb#UU5Z#K!_os3ahU&B{QHCrBi#!3|6QV^Q=SApJ2Bh)0_>$&-{@q#1BcfmT&V@6X}0wbgL}cnf-Fe=$xu3#%y^6i+CB{xUr~I?8Kp66uZoGi8bg@qi~jeI<2&tErii@zXsRa~PoA!$^YeG~MT zQ|%hE>Ek<(oMi`H)p@tAI6t4lyRjAxbWq<*aa}eA0p*dNDQj>!mlqR91Rkx3K^#b5 zj;YMWuBl{LMKJEY%W!h-{JznAnZ51I06Plv4?K zkZ0gaoR2K^6o&|!3XygI)O?j-LtG`q@D88zzKu6IU35hhteweZ2PG|Ha;V3r;p3ST zwt*%BT`Mxm;sO0A!LuNr&q^{jn99OXF&eI^EuZmh!dhW&F-_YEJtyJkch(VXnmGKf z45)F@zqdxFF^?M*^h1)A%l=4rtL-+@=O9I#BIC)>rp42dmSiC73(fX2>Up?g*Sp$D zuFr}*GEpJQ33tHgGJFU6Ws14CnkQ=mBLD7>r)lKMDXaN@GjuYkPIybubUn;6lru8zTYFAP&bK=!3}C$70Nzi3UbP#0ZMUO+zP@h& z{xGcqN9dQb${woTB}tK}WX%~wy8^Qju5u1#NB8}i@3Yq@RwllONTmyzP8?sY8fuGu zG=bd6<+(NEqGCe@xsqNBP1`A$RhKqhW9jZKnD(wE-6wjzkW|&x3EX1D2#0~w54~)K zqJ7lzWirxi4>iJN17$2_DkQ|IOcH7i0yXwkRz5uYah6O!^heZIYaIeBuvuzKtp*ca zI*AIF;e3->U@Q%alP&B*#&;x3qL(I3XJajlE1GVw!ZoD^Qys2OF1_Z7vwTl~I35L- z#(&lFj923jaY_vi&JW2j4sYlZ8~H+wea;N+uj~?r9e$t~xJ|oCe%$~=E#beD>v|Qg z6w}ryP-NJ5Hy^{*v)D=>%XF{@Xb=KLsSSjuazF4IMyOy&+Pmy7K62~g zCaXOLl|si2x*mQaoFgR;M_%7tehDuh^?2wW!UGa;JAeZp6g%03d32MxpS&h|Od5L5 z?FhYynHANDf`|(e#FSt7|602eXehfkK8ngNTeK-jMM5Q&Haj7*l%!?sgF!RM((`xtnZR+R3{O zpG(>%&tIvs?6bL2)a%Q|qr4=<(TMMZJ z9kWKin;s(ai?QRWB=O_~9Vl)bM{ZJOJyg7?e;t>gzs6at!S4TD_~3v?j^tgf2pco* zhnbtiHI)w7h!@vdmz-RpLV)U-^-Bvg_+(E`SNf+l2<#EGe|+w>#>~&Q zUJ9=>uZ!Fo6XKNmFpKKOT`q2XHg^8=pO^Ph-!C+A71U2la=0^$@>QqCTxVf@-Jc7c zQP=M$opqv2nWvCiT;f~&xhX|2W73CBi49tT-X{{rsa#l~?RoF%i#+w*CcCG}W3Sr9 zr*4&N7-K5px+o|1s`a#2*|w3B8`Ayi=9TL!#R{H1m-kTjY3GA!PC7OthFXtEkXb2x z!_?>%&*jS@mohK8&)F587hqQXCemZHfOhifMCgP*R}*R!Vs*EdpQ~^gVH!PhxSFu> zZb{0Jr@0Y<6CFNSW>ieGwzJM^O=;=OuAHu}d!*x2z?xYK0uMeE`R7N3@t?0AQM@th z)5SYGheoz!OAUhuXd|9w=FFDUv;Pw>apJS`&(|^!Iz-g9K8{{B{$j2ibiRNc8KQ>5 zhHC!Y2af*Ys#L$28+yNPN_zR{t1Cr{`33e!_}t5il$xM+<%gHP`$;(Yqw!d_ZO#YU z&n<~5L*gPQ7hI=*lrFRPyAt`dVZN4W?c*JyZn7dmF){91lk>t9^+)^`eP8=%< zqwbc{E6>ZL+u!dh6}a+ob8(XKlT(ibep@Uk59Oe`SC^`jBs9r2PQb?WsDK7 zJ1?_r#Lhf-o>E%l+c4yS1>|63?4Ddtz}!!mg|fja1(&^10#4 z*HYJN%01=UM2f#5Rq39PWPSWd>#dcC6;+wnUs&y zPLA33GkBV7(Z{Keyhd?fH*gNp|FR-RrM~UT5kY?0!~fUehWwH`&{_4&+!>uTCfHX9@0|8xy zlqNT>IItpf%rdK7HHVI24U>-UZC_rja(w;7@PpPTW#1j!l>N4B?}D^Mg9&99s)v@f z-CT1~N!7T~L}y`MlW54cJ9=hD4Izot*yj$ll4PspaD%w|lw&P3uflVyhi9zFta)Ho zXrKK~;klU3lFTu)huO5qNtfk6;;j`nA0n0LS*w1^D=PoqsiDuLst8gr0)tL)6H z2TS9&ZVw2*rYh?^!b5E3YmGYXm09;!W{FA_Zicsd4v3ej21szrz7yZoyeo8G&!VOM&t?eo}(TIr&OtG{^n?XL3`wcj`Fwci)=^6{byPGRn8 z(^7-t4?Wtm_=f(&Go;BI&n%ZS{$94UjhFJ-O*W9eF=OaqkBJYI98!XfFGqh=4EQN!8-f9+Krk)v{evpDtwlZuTq-*}$#A zM(Q3u7NUlCFBe?9Tu>wt;AFElDa_>MF^yN7ULAe6;M8K%f;f`(H6xydp^66Um)^(- zlCDrVq-}mP zJ0Z|wRK0KN#j~sY^WCE5b19Nnmp?hsp0BJ{Jv$!k?PD+zZ5%hY3WMK1vmMw*Yen1SIL;EzTzA$HIdi3ZS(T8 z^RuV9_@>&faLZnPfBMpNs$Qd>ex=h$tMu@5;iHZx+0hlMqc>1eXBBtm$j>f~Fi!LB z$dJ9AnUl1TTfr^z?Oy6jIV-tiS+?%i4`xeb*ONjz{Sq5X18sZ+HtSw8e{tY|y85l6 zjM(zgVOOLphHW;;wW-nxBWI3#5}Q(Y&GN*d>7!2FrM$|_OA?s>QaUWNg)cPW$f7MB zHC!)+;_fU8Fp6=I`)#4We%(U);y5nTx}789T!;S0B@okEY$7o7mQN>7So9KdN@S$W zd+P0@4x5b3bw+>Raqn>G?1EOAk2MobYM%ZHy%znae0bRA&YwS}w#C_(YUqy$(RgcC z`g>T|g{8yE`{!pziu_o%XL8i-3kN6b(FDY#lK-5N8X13l^U=>zdQT^Mp+$Ntcc9ME*=|93JX3R6;|4_nxuIQ@9^b)0(+ym*Ag?Z`Y)Wb(GSJa!fiIeaBG$ zwC5}6JGz8@hs`ErM&B`WCwn`2(x`flWN#muqmH9D9J%YcTOQV(yRMzi@_93Nw#kuw z`r9&>ln!-Ys&1fbu;8JUOUf{wX*q^7O&WhJH@UI@#VRUf$Hh!nhyjwWSv;&D7MkW zQi`w1OIb);dF<@#$>eoE`iY<{!TMrs>*Z^ zx#qYpC>GuRGalaKsyyQAD;#z-@y6z57AF!!xwL&JJUqWEGT3rb2<^qY7E9&Phtw=> zQ=Yn+j#Cj=&aOIaZ0E`=RUy`XGx2JrS&DbcsPkcsZ(rE8=&ppdBmbFbXUwmP$ z!Paf}PFEF7TBlrb)b6XGaq~EVM3akmQ=l68V7K=(%L&5AM~F>Mp-Ma28jdyEr>37} zU=XMw_RcZjmO=czg8ef$)XDLl_+)%=QP`KVE##2)H74`3zcP*>Kb$ctdn&kM!eCZ1 z8LntWqv(3rdpbCFzig0dwR+_kEAdVt-op-3e1hVNU+t#em$TKQR%O^OH5i&25_EN1 zs)VWhP8I6Ry=sSRzm`0lUBPdm zC&OI%7Fno9R!*85r5qAnq;xeW)o!Gb!hv+r8{;I-8Yo&@L@!s}ku%aE{k+}K4%w_I z<)rqNd^ECq%6h-!>m$ggEp1I3B|_Fn2x(96*zu>-r#!>QK3+rV=^N>-ZKtQtJRSTw zz*n8F9H*?Jvw8dcE3N^BKE`MDMqih1aJ~A7R-W4=DG=@=ojdJ=IxW-U!MgW)Ydlx| zI`iK5*;U1{5j8&7JzlFdoUaOAdzNJjhs*W1Pqk$wz6sW!k@MrC2hYJVrt1C=jKtJLwf)LYZxl_H zY|XR}^|5gBdOla1Uo`IN;uXHDMKWLb@|}AsI>YTy@o>KU>gbypA^eBT%JWh`PZpk=%S|4Z-Dko@xy`)JaWIl*PNI z1nhf7P8_@IUZv~NP6w`7%4mmrlV=NUPd>i;Gec&{zI;kOWwF7`(OUx6B`C+OkWVU` zB=D>C%-W=lrDAJ~c7Cqj#8a%I>&9K9(x{qmSpU&@;gSj86@!NQeU~iy#mg-rGjd{> z%63>^9(gfC=QsdDq2@vR-hRe7hAoNz?6+!DLmVC-lz}Cw-cR zZq<&mm~*o8yTj~X{IbgQG}Vk*f!uAvQKlpK=8f=+ymOE5T=a9H!t=gy!Mt9DMxuq$ ztIPh_FU}U^iNE_jxzTcl7|(axMc3X>yfbe7bCDBiD&I!CPZ=#ZmfR{aWM)b0j&jBE z+eSux5>#$KvXwE0iO7&0I_;^WB`$IkxT}w?R z!)1EPowxe_>ATe7^{e4;hXJfO@@EU-Uw{A9M01&;p00)E3=_!5*^>(+2=##b7lBIl zb@YIXZrJ}ZR+R7kq(N4eKZc8}W-zX=B0`bvg@E741Sq}NVX@+!Sy1@_+c}7xFvI@a z`(5f6o|h+eh8NA#%aP_yailY&JItAH^{U16i-s79RC0hsn$`;qziEQ$*vZ`6S`6Kf z>dp+y>IA3@JQ&qADIod_UZf$z!4`k74I}z95QFJk!u)5w4Q2+wN?Iw7qjn92CWe8} zq3Yd^51`{i1znnYc~d++=yHrhC*J-&`@UGwqja@y$pAXJ5Bl@5Oj7kW4@EbocsOdo zw%+bl8&>q3Ytjw6;McjpFqcVm;G5VF^ktqNW;BY2H&#lwU@yb&`8%}yfME}q1v_rs z`w7VPgQe?800F-4>en9I!Ig_(^E0-^x%YcMwIBE^9BFhgMOXcVRYSiQtCafjkw|C9 zkx25r!0_93xLM_|SFzDQK4#4El44D0Zz{&ag9h2e#vSbzigsj?tzls)4^++uv5zIwr=DXy4G9|3050BNu*5qm#+ zV82+fu>v3Z=A!X=>YylVa5ogXdP~2cv0&2|n%J5y+t@+FIxal3#~NO)i(0JogAu#| zT8Q?w3=T+LOT+BC#H!XU5ftbWiJ$;1h3frw>?dwv4=&5C$IK09RRJ0ommOq7;6eAM z`CuiRK3e#>q`e>Z`0wo@45ZQ237s#>And9 zpDtYNxmGDmT@Fqpk(MBILgj;_>q@}z+4#gaI`Z+8NNSLkYawhp4TEIszFiQXZ^p;u z79a4tPkbbj4#JoJa&Uau;ALv(3K1NiF*kXWOf+P!tso(q-zU8t2qQjv<%Q;w5^%aZ z5V^6pFnhnfUj~9s5M!_&bX#?;{4od%E zc34-5H|}>qsz#6s9a$@WaHP|LKtQo4dt*-za}aBIwOba(^9e*lqaF8ejyx7*CnOT7 z;#(-4XNu=yz!wJ9>Gzrkew+Jez#M-yXXWAG=mZ0<13szs(a|=JKq?KS1_)^@7Z=_X z!M-PC!ID*8!<6BIs{{eQrXFA zS2JuP4LECn6Lq0N7|(I$)BWx&W@HMDj<4K~4J)=8f?_xJvFB;Ie|3^x1HdD}RdrtTq83xzd3Xn)fNZ-tx z@o$ut6sjZLn@nZXUDnV2uOwB1MEVRhDm2Ty2XAc*%#HdQkTugEgNXLT2$#XJYp&iW z%eRa)YR1ylXYhj-T@{T9fw0Lx`*Ow6qgSfOLHthzYbzk_n{L7p7HSIYCcqWKc{XA& zres05#diJmehH@i!qxTjg8YneAAEQ23%NmG9b=i!FMGKdW8kvw6M!aI4wB1)LWOg= zjPnopoN+;i_W6L$enZDx(kmSN_QZOSoCIty78O3WfpGT(<`gK~b=!fm_1s9Ca-PSJ!rx%6@gh_(v`BOQb=+1RKZN@xcW7I)_-#$d8#P(|S{XykW3vk}` zA?-N8mcx${0$|{pl2( zi3Dp>2qh+_&-pPvxQB0_gs`nfrZE-%v=e^NBK3LpAi5sDT@CzOAb=txn<~hHC5LGn z!1d%IR-h?d?i04H#3lGk2LBh|Q8Z&0%*g>&AAt~vI?Cba1LEon&#G`~CUuiYm!PVR zmjKXcIFg+-Iv+?5e!ybMh~GrG-7AT(83EE{0{l_i@|~oi%_%U7qBGSmo&CdS z1b+esy}+CI6rj7?frF#A^BOt?*LGbRW?rzw*NvLYJIP$o%UM82%juto5h3>^hs2uU znH~Qq1uQxR+Ku)hA>RI=bJ7bvL-^ZRX!#5%P)tQUPfCCYpP}l%*Y&X0T~i{Sh%Nxs zW?sz^wb9W~T8s$N5T?2mdx|%~YTQk|V`Uq_g2K>ZbTm9C zK?L2MYZDvr^T9l72(()hRDs6+0Jy*aFKBc*UN<-=`!$rgEw}@1&w{q2g_CuoiQus< z83f%$_{iouE*P=+U@TBX47g(~5p37+O8_jmU@n(8v{ww;i}sc#DAco8M^C;=tn5~D z`K?e;wk{|e?JXB3^#`4kw)uT*9y&nlv0Dw%Rn2z~r&xL!aW~^aH zI)P?-lV3LItRoC8JTraL3i#-L-ted{wxbWp%~-KeEjV+;vWHXaupsZ@3CSsdBiPtT zWAXF1NdfBlpSZ#m^rpMF}NSjqS zsf<<3zD>c8az{ko=Y)fEU4Xua&hXlo43bla>`lfeTdlg6hOMFM0htLR;0x`6l9|Cp z8f0f!eq>d7Uusqt8jDbO>anG!!L$Q$7*?bS2+~r0VkA3C03jNhCdBpw%?`GL%$co? z9sWR&F~=75KD+i=p&!dbbfN+QjPRRV5{G@MnzQxF9=^#je> z)6?1Akq{Ie&DAV8H?bSk*#TUe5E>l=Vg?G`b+(LPPdvK8;q##ILFZJKK**|gbbh+V za)26Qh|x`hxhSGC%r}E38w+HEX+>aYGeS&U{?A;xbbB)F4)5!!7_ry{uY?SkfE&T~ z9&?1a6Ly2*jd?ICF~R`msfZi&71EJrkL?a6;y>eNt;`LXbv&dwmI(jMb^pq5b@ACg`L0=zWb@T~{ z4H9U${IEZt=1Ira&v1$ubTbR11u&*LLk@vvQ6Kt&rsYWX(6qOAq~nyfFn`@o7jYf} z$Pd70(W+F059hY(Q5@YJ%(@PquvzTm;_}Fj0|G@bh#I1dc7M(U`i>rsG>Sbjg_Mx) z4oUF&8t8NAT)TY>X9^QXZx>GvLPQ*Xc`^oU&<1%0Duffvgm8K_Vo{T>@(i&MH;&tn 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 OCF%edL7au$oAf{YX@{u* literal 0 HcmV?d00001 From f02bad8e8a775bc81a48804ff19144b319a14239 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:55:12 +0530 Subject: [PATCH 30/38] refactored the implementation using util methods implementation can handle different types of dispatchers (cherry picked from commit dcd10fe36c174cc5e92c451397dd14e16a31309a) --- .../apimgt/gateway/handlers/LogUtils.java | 165 +++--------------- .../apimgt/gateway/handlers/LogsHandler.java | 2 +- .../carbon/apimgt/gateway/handlers/Utils.java | 62 +++++++ .../handlers/security/CORSRequestHandler.java | 23 +-- 4 files changed, 90 insertions(+), 162 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 20629ab22602..cf7d0e8a9936 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -26,13 +26,7 @@ import org.apache.synapse.api.Resource; import org.apache.synapse.api.dispatch.DispatcherHelper; import org.apache.synapse.api.dispatch.RESTDispatcher; -import org.apache.synapse.api.dispatch.URITemplateBasedDispatcher; -import org.apache.synapse.api.dispatch.URITemplateHelper; -import org.apache.synapse.api.version.DefaultStrategy; -import org.apache.synapse.api.version.VersionStrategy; -import org.apache.synapse.config.xml.rest.VersionStrategyFactory; import org.apache.synapse.core.axis2.Axis2MessageContext; -import org.apache.synapse.rest.RESTConstants; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.impl.APIConstants; @@ -131,83 +125,44 @@ protected static String getTransportInURL(org.apache.synapse.MessageContext mess return transportInURL.substring(1); } - protected static String fetchLogLevel(MessageContext messageContext, - Map, String> logProperties) { + protected static String getMatchingLogLevel(MessageContext messageContext, + Map, String> logProperties) { //initializing variables to store resource level logging - String subPath; - API selectedApi = null; String apiLogLevel = null; String resourceLogLevel = null; String resourcePath = null; String resourceMethod = null; Resource selectedResource = null; - //getting the API collection from the synapse configuration to find the invoked API - Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); - List duplicateApiSet = new ArrayList<>(apiSet); + //obtain the selected API by context and path + API selectedApi = Utils.getAPIByContext(messageContext); //obtaining required parameters to execute findResource method String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). getProperty("TransportInURL").toString(); String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext(). getProperty(Constants.Configuration.HTTP_METHOD); - org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext) - .getAxis2MessageContext(); - Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); - String corsRequestMethod = (String) headers.get(APIConstants.CORSHeaders.ACCESS_CONTROL_REQUEST_METHOD); - - for (API api : duplicateApiSet) { - if (apiContext.contains(api.getContext())) { - selectedApi = api; - break; - } - } if (selectedApi != null) { - //obtaining the subpath vua full request path (ex:{resource}/{id}) to invoke the findResource method - String path = ApiUtils.getFullRequestPath(messageContext); - VersionStrategy versionStrategy = new DefaultStrategy(selectedApi); - if (versionStrategy.getVersionType().equals(VersionStrategyFactory.TYPE_URL)) { - subPath = path.substring(selectedApi.getContext().length() + versionStrategy.getVersion().length() + 1); - } else { - subPath = path.substring(selectedApi.getContext().length()); - } - if ("".equals(subPath)) { - subPath = "/"; - } - messageContext.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, subPath); + Utils.setSubRequestPath(selectedApi, messageContext); //iterating through all the existing resources to match with the requesting method - Resource[] allAPIResources = selectedApi.getResources(); - Set acceptableResources = new LinkedHashSet<>(); - for (Resource resource : allAPIResources) { - //If the requesting method is OPTIONS or if the Resource contains the requesting method - if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && - Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || - (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { - acceptableResources.add(resource); - } - } + Map resourcesMap = selectedApi.getResourcesMap(); + Set acceptableResources = ApiUtils. + getAcceptableResources(resourcesMap, messageContext); if (!acceptableResources.isEmpty()) { for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) { - if (dispatcher instanceof URITemplateBasedDispatcher){ - //matching the available resources with the message context - selectedResource = dispatcher.findResource(messageContext, acceptableResources); - if (selectedResource != null) { - messageContext.setProperty(LogsHandler.SELECTED_RESOURCE, selectedResource); - DispatcherHelper helper = selectedResource.getDispatcherHelper(); - if (helper instanceof URITemplateHelper) { - URITemplateHelper templateHelper = (URITemplateHelper) helper; - for (Map.Entry, String> entry : logProperties.entrySet()) { - Map key = entry.getKey(); - //if resource path is empty, proceeding with API level logs - if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - apiLogLevel = entry.getValue(); - //matching the methods first and then the resource path - } else if (httpMethod.equals(key.get("resourceMethod"))) { - if(templateHelper.getString().equals(key.get("resourcePath"))) { - resourceLogLevel = entry.getValue(); - resourcePath = key.get("resourcePath"); - resourceMethod = key.get("resourceMethod"); - } - } + selectedResource = dispatcher.findResource(messageContext, acceptableResources); + if (selectedResource != null) { + DispatcherHelper helper = selectedResource.getDispatcherHelper(); + for (Map.Entry, String> entry : logProperties.entrySet()) { + Map key = entry.getKey(); + //if resource path is empty, proceeding with API level logs + if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { + apiLogLevel = entry.getValue(); + //matching the methods first and then the resource path + } else if (httpMethod.equals(key.get("resourceMethod"))) { + if(helper.getString().equals(key.get("resourcePath"))) { + resourceLogLevel = entry.getValue(); + resourcePath = key.get("resourcePath"); + resourceMethod = key.get("resourceMethod"); } } } @@ -256,80 +211,4 @@ protected static String fetchLogLevel(MessageContext messageContext, } } - protected static String getMatchingLogLevel(MessageContext ctx, - Map, String> logProperties) { - String apiCtx = LogUtils.getTransportInURL(ctx); - String apiHttpMethod = (String) ((Axis2MessageContext) ctx).getAxis2MessageContext(). - getProperty(Constants.Configuration.HTTP_METHOD); - String apiLogLevel = null; - String resourceLogLevel = null; - String resourcePath = null; - String resourceMethod = null; - String logResourcePath, resourcePathRegexPattern = null; - for (Map.Entry, String> entry : logProperties.entrySet()) { - Map key = entry.getKey(); - String apiResourcePath; - if (apiCtx.split("/", 3).length > 2) { - apiResourcePath = apiCtx.split("/", 3)[2]; - } else { - apiResourcePath = ""; - } - if (key.containsKey("resourcePath") && key.get("resourcePath") != null) { - logResourcePath = key.get("resourcePath"); - resourcePathRegexPattern = logResourcePath.replace("/", "\\/"); - resourcePathRegexPattern = resourcePathRegexPattern.replaceAll("\\{.*?\\}", - "\\\\w{0,}([-,_]?\\\\w{1,})+"); - } - if (key.get("context").startsWith(key.get("context") + "/") || - key.get("context").equals(key.get("context"))) { - if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - apiLogLevel = entry.getValue(); - } else if (("/" + apiResourcePath).matches(resourcePathRegexPattern) - && apiHttpMethod.equals(key.get("resourceMethod"))) { - resourceLogLevel = entry.getValue(); - resourcePath = key.get("resourcePath"); - resourceMethod = key.get("resourceMethod"); - } - } - } - boolean isResourceLevelHasHighPriority = false; - if (resourceLogLevel != null) { - switch (resourceLogLevel) { - case APIConstants.LOG_LEVEL_FULL: - isResourceLevelHasHighPriority = true; - break; - case APIConstants.LOG_LEVEL_STANDARD: - if (apiLogLevel != null && (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) || - apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF))) { - isResourceLevelHasHighPriority = true; - break; - } else { - break; - } - case APIConstants.LOG_LEVEL_BASIC: - if (apiLogLevel == null || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF)) { - isResourceLevelHasHighPriority = true; - } else { - break; - } - } - if (isResourceLevelHasHighPriority || apiLogLevel == null) { - ctx.setProperty(LogsHandler.LOG_LEVEL, resourceLogLevel); - ctx.setProperty(LogsHandler.RESOURCE_PATH, resourcePath); - ctx.setProperty(LogsHandler.RESOURCE_METHOD, resourceMethod); - ctx.setProperty("API_TO", apiCtx); - return resourceLogLevel; - } else { - ctx.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); - ctx.setProperty("API_TO", apiCtx); - return apiLogLevel; - } - } else if (apiLogLevel != null) { - ctx.setProperty(LogsHandler.LOG_LEVEL, apiLogLevel); - ctx.setProperty("API_TO", apiCtx); - return apiLogLevel; - } else { - return null; - } - } } \ No newline at end of file diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index ea53e56e5851..2e0d6c390bbd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -305,7 +305,7 @@ private String getAPILogLevel(MessageContext ctx) { Map, String> logProperties = APILoggerManager.getInstance().getPerAPILoggerList(); // if the logging API data holder is empty or null return null if (!logProperties.isEmpty()) { - return LogUtils.fetchLogLevel(ctx, logProperties); + return LogUtils.getMatchingLogLevel(ctx, logProperties); //return LogUtils.getMatchingLogLevel(ctx, logProperties); } return null; diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java index 20ef9750c002..29ef122fd74c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java @@ -41,6 +41,7 @@ import org.apache.synapse.SynapseConstants; import org.apache.synapse.api.API; import org.apache.synapse.api.ApiUtils; +import org.apache.synapse.api.Resource; import org.apache.synapse.commons.json.JsonUtil; import org.apache.synapse.config.xml.rest.VersionStrategyFactory; import org.apache.synapse.core.axis2.Axis2MessageContext; @@ -676,4 +677,65 @@ public static X509Certificate convertCertificateToX509Certificate(Certificate ce } return null; } + + /** + * Using the api context to match API path to get the invoked API from an API Collection + * + * @param messageContext MessageContext + * @return selected API based on the API path + */ + public static API getAPIByContext(MessageContext messageContext) { + API selectedApi = null; + //getting the API collection from the synapse configuration to find the invoked API + Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); + List duplicateApiSet = new ArrayList<>(apiSet); + //obtaining required parameters to execute findResource method + String requestPath = ApiUtils.getFullRequestPath(messageContext); + for (API api : duplicateApiSet) { + if (ApiUtils.matchApiPath(requestPath, api.getContext())) { + selectedApi = api; + break; + } + } + return selectedApi; + } + + /** + * Select acceptable resources from the set of all resources based on requesting methods + * + * @return set of acceptable resources + */ + public static Set getAcceptableResources(Resource[] allAPIResources, + String httpMethod, String corsRequestMethod) { + Set acceptableResources = new LinkedHashSet<>(); + for (Resource resource : allAPIResources) { + //If the requesting method is OPTIONS or if the Resource contains the requesting method + String [] resourceMethods = resource.getMethods(); + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null && + Arrays.asList(resourceMethods).contains(corsRequestMethod)) || + (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { + acceptableResources.add(resource); + } + } + return acceptableResources; + } + + /** + * Obtain the selected resource from the message context for CORSRequestHandler + * + * @return selected resource + */ + public static Resource getSelectedResource(MessageContext messageContext, + String httpMethod, String corsRequestMethod) { + Resource selectedResource = null; + Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); + String [] resourceMethods = resource.getMethods(); + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null && + Arrays.asList(resourceMethods).contains(corsRequestMethod)) || + (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { + selectedResource = resource; + } + return selectedResource; + } + } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index 852897ea2f38..a310ba7c7562 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -167,25 +167,12 @@ public boolean handleRequest(MessageContext messageContext) { Utils.setSubRequestPath(selectedApi, messageContext); if (selectedApi != null) { - if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null) && httpMethod.equals(corsRequestMethod)){ - Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); - String [] resourceMethods = resource.getMethods(); - if (Arrays.asList(resourceMethods).contains(httpMethod)) { - selectedResource = resource; - } - } - else { + if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null)){ + selectedResource = Utils.getSelectedResource(messageContext,httpMethod, corsRequestMethod); + } else { Resource[] allAPIResources = selectedApi.getResources(); - Set acceptableResources = new LinkedHashSet<>(); - - for (Resource resource : allAPIResources) { - //If the requesting method is OPTIONS or if the Resource contains the requesting method - if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resource.getMethods() != null && - Arrays.asList(resource.getMethods()).contains(corsRequestMethod)) || - (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { - acceptableResources.add(resource); - } - } + Set acceptableResources + = Utils.getAcceptableResources(allAPIResources, httpMethod, corsRequestMethod); if (!acceptableResources.isEmpty()) { for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) { From 16008d2b722dd19fceb4bf65b750f81230ffcf23 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Tue, 20 Jun 2023 19:08:50 +0530 Subject: [PATCH 31/38] fixed formatting (cherry picked from commit 6896e8439cc7431b139d83a52c8f34737c4ee530) --- .../apimgt/gateway/handlers/LogUtils.java | 22 +++++++++---------- .../carbon/apimgt/gateway/handlers/Utils.java | 18 +++++++-------- .../handlers/security/CORSRequestHandler.java | 8 +++---- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index cf7d0e8a9936..f1c3e6ae49a8 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -97,7 +97,7 @@ protected static String getElectedResource(org.apache.synapse.MessageContext mes return (String) messageContext.getProperty("API_ELECTED_RESOURCE"); } - protected static String getResourceCacheKey(org.apache.synapse.MessageContext messageContext){ + protected static String getResourceCacheKey(org.apache.synapse.MessageContext messageContext) { return (String) messageContext.getProperty("API_RESOURCE_CACHE_KEY"); } @@ -136,17 +136,17 @@ protected static String getMatchingLogLevel(MessageContext messageContext, //obtain the selected API by context and path API selectedApi = Utils.getAPIByContext(messageContext); //obtaining required parameters to execute findResource method - String apiContext = ((Axis2MessageContext)messageContext).getAxis2MessageContext(). - getProperty("TransportInURL").toString(); - String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext(). - getProperty(Constants.Configuration.HTTP_METHOD); + String apiContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext() + .getProperty("TransportInURL").toString(); + String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext() + .getProperty(Constants.Configuration.HTTP_METHOD); if (selectedApi != null) { Utils.setSubRequestPath(selectedApi, messageContext); //iterating through all the existing resources to match with the requesting method - Map resourcesMap = selectedApi.getResourcesMap(); - Set acceptableResources = ApiUtils. - getAcceptableResources(resourcesMap, messageContext); + Map resourcesMap = selectedApi.getResourcesMap(); + Set acceptableResources = ApiUtils + .getAcceptableResources(resourcesMap, messageContext); if (!acceptableResources.isEmpty()) { for (RESTDispatcher dispatcher : ApiUtils.getDispatchers()) { selectedResource = dispatcher.findResource(messageContext, acceptableResources); @@ -159,7 +159,7 @@ protected static String getMatchingLogLevel(MessageContext messageContext, apiLogLevel = entry.getValue(); //matching the methods first and then the resource path } else if (httpMethod.equals(key.get("resourceMethod"))) { - if(helper.getString().equals(key.get("resourcePath"))) { + if (helper.getString().equals(key.get("resourcePath"))) { resourceLogLevel = entry.getValue(); resourcePath = key.get("resourcePath"); resourceMethod = key.get("resourceMethod"); @@ -177,8 +177,8 @@ protected static String getMatchingLogLevel(MessageContext messageContext, isResourceLevelHasHighPriority = true; break; case APIConstants.LOG_LEVEL_STANDARD: - if (apiLogLevel != null && (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) || - apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF))) { + if (apiLogLevel != null && (apiLogLevel.equals(APIConstants.LOG_LEVEL_BASIC) + || apiLogLevel.equals(APIConstants.LOG_LEVEL_OFF))) { isResourceLevelHasHighPriority = true; break; } else { diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java index 29ef122fd74c..0e5f1c5047ea 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java @@ -679,7 +679,7 @@ public static X509Certificate convertCertificateToX509Certificate(Certificate ce } /** - * Using the api context to match API path to get the invoked API from an API Collection + * Using the api context to match API path to get the invoked API from an API Collection. * * @param messageContext MessageContext * @return selected API based on the API path @@ -701,7 +701,7 @@ public static API getAPIByContext(MessageContext messageContext) { } /** - * Select acceptable resources from the set of all resources based on requesting methods + * Select acceptable resources from the set of all resources based on requesting methods. * * @return set of acceptable resources */ @@ -711,9 +711,9 @@ public static Set getAcceptableResources(Resource[] allAPIResources, for (Resource resource : allAPIResources) { //If the requesting method is OPTIONS or if the Resource contains the requesting method String [] resourceMethods = resource.getMethods(); - if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null && - Arrays.asList(resourceMethods).contains(corsRequestMethod)) || - (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null + && Arrays.asList(resourceMethods).contains(corsRequestMethod)) + || (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { acceptableResources.add(resource); } } @@ -721,7 +721,7 @@ public static Set getAcceptableResources(Resource[] allAPIResources, } /** - * Obtain the selected resource from the message context for CORSRequestHandler + * Obtain the selected resource from the message context for CORSRequestHandler. * * @return selected resource */ @@ -730,9 +730,9 @@ public static Resource getSelectedResource(MessageContext messageContext, Resource selectedResource = null; Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); String [] resourceMethods = resource.getMethods(); - if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null && - Arrays.asList(resourceMethods).contains(corsRequestMethod)) || - (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { + if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null + && Arrays.asList(resourceMethods).contains(corsRequestMethod)) + || (resourceMethods != null && Arrays.asList(resourceMethods).contains(httpMethod))) { selectedResource = resource; } return selectedResource; diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index a310ba7c7562..70098e275a6e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -155,8 +155,8 @@ public boolean handleRequest(MessageContext messageContext) { } String apiContext = (String) messageContext.getProperty(RESTConstants.REST_API_CONTEXT); String apiVersion = (String) messageContext.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION); - String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext(). - getProperty(Constants.Configuration.HTTP_METHOD); + String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext() + .getProperty(Constants.Configuration.HTTP_METHOD); API selectedApi = Utils.getSelectedAPI(messageContext); org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext) .getAxis2MessageContext(); @@ -167,8 +167,8 @@ public boolean handleRequest(MessageContext messageContext) { Utils.setSubRequestPath(selectedApi, messageContext); if (selectedApi != null) { - if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null)){ - selectedResource = Utils.getSelectedResource(messageContext,httpMethod, corsRequestMethod); + if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null)) { + selectedResource = Utils.getSelectedResource(messageContext, httpMethod, corsRequestMethod); } else { Resource[] allAPIResources = selectedApi.getResources(); Set acceptableResources From 91eff3ca031d59e2a5e90de260109aaac2aae511 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:33:53 +0530 Subject: [PATCH 32/38] move constant from logshandler to restconstants (cherry picked from commit b8cb215349680bd451e97e6b087a638245b63073) --- .../org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java | 2 -- .../java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java | 2 +- .../apimgt/gateway/handlers/security/CORSRequestHandler.java | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java index 2e0d6c390bbd..2e08c51bbec0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogsHandler.java @@ -56,8 +56,6 @@ public class LogsHandler extends AbstractSynapseHandler { protected static final String LOG_LEVEL = "LOG_LEVEL"; protected static final String RESOURCE_PATH = "RESOURCE_PATH"; protected static final String RESOURCE_METHOD = "RESOURCE_METHOD"; - public static final String SELECTED_RESOURCE = "SELECTED_RESOURCE"; - private static final String REQUEST_BODY_SIZE_ERROR = "Error occurred while building the message to calculate" + " the response body size"; private static final String REQUEST_EVENT_PUBLICATION_ERROR = "Cannot publish request event. "; diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java index 0e5f1c5047ea..51cec359319e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java @@ -728,7 +728,7 @@ public static Set getAcceptableResources(Resource[] allAPIResources, public static Resource getSelectedResource(MessageContext messageContext, String httpMethod, String corsRequestMethod) { Resource selectedResource = null; - Resource resource = (Resource) messageContext.getProperty(LogsHandler.SELECTED_RESOURCE); + Resource resource = (Resource) messageContext.getProperty(RESTConstants.SELECTED_RESOURCE); String [] resourceMethods = resource.getMethods(); if ((RESTConstants.METHOD_OPTIONS.equals(httpMethod) && resourceMethods != null && Arrays.asList(resourceMethods).contains(corsRequestMethod)) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java index 70098e275a6e..604293b1ac0e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandler.java @@ -167,7 +167,7 @@ public boolean handleRequest(MessageContext messageContext) { Utils.setSubRequestPath(selectedApi, messageContext); if (selectedApi != null) { - if ((messageContext.getProperty(LogsHandler.SELECTED_RESOURCE) != null)) { + if ((messageContext.getProperty(RESTConstants.SELECTED_RESOURCE) != null)) { selectedResource = Utils.getSelectedResource(messageContext, httpMethod, corsRequestMethod); } else { Resource[] allAPIResources = selectedApi.getResources(); From 9d0963534afbfcb1b15c10c1b66aad4454970889 Mon Sep 17 00:00:00 2001 From: Chamika Sudusinghe <44718392+chamikasudusinghe@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:21:01 +0530 Subject: [PATCH 33/38] using synapse util to find the api (cherry picked from commit 8f0e2c25cd81b8612a9a4975c3cbb4bb10347798) --- .../java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index f1c3e6ae49a8..23482f59022c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -134,7 +134,8 @@ protected static String getMatchingLogLevel(MessageContext messageContext, String resourceMethod = null; Resource selectedResource = null; //obtain the selected API by context and path - API selectedApi = Utils.getAPIByContext(messageContext); + //API selectedApi = Utils.getAPIByContext(messageContext); + API selectedApi = ApiUtils.getSelectedAPI(messageContext); //obtaining required parameters to execute findResource method String apiContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext() .getProperty("TransportInURL").toString(); From a0cfc0515830830acba48e1dd2b44cea41d11d19 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 17 Jul 2023 17:38:47 +0530 Subject: [PATCH 34/38] Api identification added to getMatchingLogLevel method. --- .../carbon/apimgt/gateway/handlers/LogUtils.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 23482f59022c..80c4f0b31caa 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -134,9 +134,15 @@ protected static String getMatchingLogLevel(MessageContext messageContext, String resourceMethod = null; Resource selectedResource = null; //obtain the selected API by context and path - //API selectedApi = Utils.getAPIByContext(messageContext); - API selectedApi = ApiUtils.getSelectedAPI(messageContext); - //obtaining required parameters to execute findResource method + API selectedApi = null; + Collection apiSet = messageContext.getEnvironment().getSynapseConfiguration().getAPIs(); + //identify the api + for (API api : apiSet) { + if (ApiUtils.identifyApi(api, messageContext)) { + selectedApi = api; + break; + } + } String apiContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext() .getProperty("TransportInURL").toString(); String httpMethod = (String) ((Axis2MessageContext) messageContext).getAxis2MessageContext() From 4f921fc9d267edb3f8fe32775101e0599738df30 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Mon, 17 Jul 2023 17:39:39 +0530 Subject: [PATCH 35/38] Unit test failures fixed by adding mock to the Utils.getAcceptableResource method. --- .../handlers/security/CORSRequestHandlerTestCase.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandlerTestCase.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandlerTestCase.java index 01ff2383e50e..0f0c9bb1946c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandlerTestCase.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/handlers/security/CORSRequestHandlerTestCase.java @@ -47,7 +47,9 @@ import org.wso2.carbon.metrics.manager.Timer; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import java.util.TreeMap; /** @@ -124,6 +126,10 @@ public String getString() { TreeMap transportHeaders = new TreeMap(); transportHeaders.put("Origin", ""); + Set acceptableResources = new LinkedHashSet<>(); + acceptableResources.add(resource); + String httpMethod = "GET"; + Mockito.when(Utils.getAcceptableResources(resources, httpMethod, null)).thenReturn(acceptableResources); Mockito.when(axis2MsgCntxt.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS)).thenReturn(transportHeaders); Assert.assertTrue(corsRequestHandler.handleRequest(messageContext)); @@ -136,12 +142,13 @@ public String getString() { }; Mockito.when(resource.getDispatcherHelper()).thenReturn(dispatcherHelper1); - - Mockito.when(axis2MsgCntxt.getProperty(Constants.Configuration.HTTP_METHOD)).thenReturn("OPTIONS"); + httpMethod = "OPTIONS"; + Mockito.when(axis2MsgCntxt.getProperty(Constants.Configuration.HTTP_METHOD)).thenReturn(httpMethod); //test for OPTIONS request when OPTIONS is not supported by SupportedHTTPVerbs Assert.assertFalse(corsRequestHandler.handleRequest(messageContext)); //test for OPTIONS request when OPTIONS is supported by SupportedHTTPVerbs String[] methodsWithOptions = {"GET", "POST", "OPTIONS"}; + Mockito.when(Utils.getAcceptableResources(resources, httpMethod, null)).thenReturn(acceptableResources); Mockito.when(resource.getMethods()).thenReturn(methodsWithOptions); Assert.assertTrue(corsRequestHandler.handleRequest(messageContext)); From 0b7f8376b9c9b9d483fb436284e64668b67c3430 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 18 Jul 2023 10:32:58 +0530 Subject: [PATCH 36/38] formatted logging related sql scripts --- .../impl/dao/constants/SQLConstants.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) 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 469761d24329..1578adfa6194 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 @@ -3013,44 +3013,61 @@ public class SQLConstants { public static final String ADD_PER_API_LOGGING_SQL = "UPDATE AM_API SET LOG_LEVEL=? WHERE API_UUID=? AND ORGANIZATION=?"; public static final String ADD_PER_API_RESOURCE_LOGGING_SQL = - "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; + "UPDATE AM_API_URL_MAPPING SET LOG_LEVEL= ? WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ?" + + " AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; public static final String CHECK_PER_API_RESOURCE_IS_AVAILABLE_LOGGING_SQL = - "SELECT * FROM AM_API_URL_MAPPING WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; + "SELECT * FROM AM_API_URL_MAPPING WHERE API_ID = (SELECT API_ID FROM AM_API WHERE API_UUID= ? AND " + + "ORGANIZATION= ?) AND HTTP_METHOD = ? AND URL_PATTERN = ?"; public static final String RETRIEVE_PER_API_LOGGING_OFF_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_OFF_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN " + + "AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' " + + "AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BASIC_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON " + + "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_STANDARD_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_STANDARD_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT," + + " AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID " + + "WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_FULL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_FULL_SQL = - "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; + "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON " + + "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; public static final String RETRIEVE_ALL_PER_API_LOGGING_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; public static final String RETRIEVE_ALL_PER_API_RESOURCE_LOGGING_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE AUM.LOG_LEVEL <> 'OFF' AND AUM.REVISION_UUID IS NULL"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, API.CONTEXT, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + + "API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID " + + "WHERE AUM.LOG_LEVEL <> 'OFF' AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_ALL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_ALL_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_NAME, API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_NAME, API.CONTEXT," + + " API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON " + + "AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; public static final String RETRIEVE_PER_API_LOGGING_BY_UUID_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.API_UUID = ? AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BY_UUID_SQL = - "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, AUM.HTTP_METHOD ,AUM.URL_PATTERN , API.CONTEXT, API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = API.API_ID WHERE API.API_UUID = ? AND API.ORGANIZATION= ?"; + "SELECT API.API_UUID, AUM.LOG_LEVEL, API.API_NAME, AUM.HTTP_METHOD ,AUM.URL_PATTERN , API.CONTEXT, " + + "API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON " + + "AUM.API_ID = API.API_ID WHERE API.API_UUID = ? AND API.ORGANIZATION= ?"; public static final String GATEWAY_LABEL_REGEX = "_GATEWAY_LABELS_"; public static final String API_ID_REGEX = "_API_IDS_"; public static final String API_UUID_REGEX = "_API_UUIDS_"; From c824e59902ed843ee12aef90434df73b45e10091 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Wed, 19 Jul 2023 14:23:44 +0530 Subject: [PATCH 37/38] logging queries changed to not return revisioned apis. --- .../apimgt/impl/dao/constants/SQLConstants.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 1578adfa6194..404a43dd5324 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 @@ -3025,28 +3025,30 @@ public class SQLConstants { "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN " + "AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'OFF' " + - "AND AM_API.ORGANIZATION= ?"; + "AND AM_API.ORGANIZATION= ? AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_BASIC_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_BASIC_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON " + - "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?"; + "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'BASIC' AND AM_API.ORGANIZATION= ?" + + "AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_STANDARD_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_STANDARD_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, AM_API.CONTEXT," + " AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON AUM.API_ID = AM_API.API_ID " + - "WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ?"; + "WHERE AUM.LOG_LEVEL = 'STANDARD' AND AM_API.ORGANIZATION= ? AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_FULL_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION=?"; public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_FULL_SQL = "SELECT AM_API.API_UUID, AUM.LOG_LEVEL, AM_API.API_NAME, AUM.HTTP_METHOD, AUM.URL_PATTERN, " + "AM_API.CONTEXT, AM_API.API_VERSION FROM AM_API INNER JOIN AM_API_URL_MAPPING AUM ON " + - "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?"; + "AUM.API_ID = AM_API.API_ID WHERE AUM.LOG_LEVEL = 'FULL' AND AM_API.ORGANIZATION= ?" + + "AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_ALL_PER_API_LOGGING_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.LOG_LEVEL <> 'OFF'"; @@ -3060,7 +3062,7 @@ public class SQLConstants { public static final String RETRIEVE_PER_API_RESOURCE_LOGGING_ALL_SQL = "SELECT API.API_UUID, AUM.LOG_LEVEL, AUM.HTTP_METHOD, AUM.URL_PATTERN, API.API_NAME, API.CONTEXT," + " API.API_VERSION FROM AM_API API INNER JOIN AM_API_URL_MAPPING AUM ON " + - "AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ?"; + "AUM.API_ID = API.API_ID WHERE API.ORGANIZATION= ? AND AUM.REVISION_UUID IS NULL"; public static final String RETRIEVE_PER_API_LOGGING_BY_UUID_SQL = "SELECT AM_API.API_UUID, AM_API.LOG_LEVEL, AM_API.API_NAME, AM_API.CONTEXT, AM_API.API_VERSION " + "FROM AM_API WHERE AM_API.API_UUID = ? AND AM_API.ORGANIZATION=?"; From de3deca306d0e38abd7fab69eb2c3fde56ef1bb1 Mon Sep 17 00:00:00 2001 From: shnrndk Date: Tue, 25 Jul 2023 14:30:31 +0530 Subject: [PATCH 38/38] Added match identified api context with the log properties --- .../apimgt/gateway/handlers/LogUtils.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java index 80c4f0b31caa..09b67ada7572 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/LogUtils.java @@ -162,14 +162,16 @@ protected static String getMatchingLogLevel(MessageContext messageContext, for (Map.Entry, String> entry : logProperties.entrySet()) { Map key = entry.getKey(); //if resource path is empty, proceeding with API level logs - if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { - apiLogLevel = entry.getValue(); - //matching the methods first and then the resource path - } else if (httpMethod.equals(key.get("resourceMethod"))) { - if (helper.getString().equals(key.get("resourcePath"))) { - resourceLogLevel = entry.getValue(); - resourcePath = key.get("resourcePath"); - resourceMethod = key.get("resourceMethod"); + if (selectedApi.getContext().equals(key.get("context"))) { + if (key.get("resourcePath") == null && key.get("resourceMethod") == null) { + apiLogLevel = entry.getValue(); + //matching the methods first and then the resource path + } else if (httpMethod.equals(key.get("resourceMethod"))) { + if (helper.getString().equals(key.get("resourcePath"))) { + resourceLogLevel = entry.getValue(); + resourcePath = key.get("resourcePath"); + resourceMethod = key.get("resourceMethod"); + } } } }