aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--a1-policy-management/config/application.yaml2
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java49
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientFactory.java19
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java10
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java13
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientConfig.java9
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/ServiceCallbacks.java2
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java3
-rw-r--r--a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java6
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientTest.java2
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClientTest.java2
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ApplicationTest.java3
-rw-r--r--a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java3
13 files changed, 81 insertions, 42 deletions
diff --git a/a1-policy-management/config/application.yaml b/a1-policy-management/config/application.yaml
index b5cfd514..823b93b2 100644
--- a/a1-policy-management/config/application.yaml
+++ b/a1-policy-management/config/application.yaml
@@ -56,4 +56,6 @@ app:
trust-store-used: false
trust-store-password: policy_agent
trust-store: /opt/app/policy-agent/etc/cert/truststore.jks
+ http.proxy-host:
+ http.proxy-port: 0
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java
index 7f453a27..cba1c7cc 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java
@@ -28,6 +28,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler;
import java.lang.invoke.MethodHandles;
import java.util.concurrent.atomic.AtomicInteger;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig.HttpProxyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
@@ -42,6 +43,7 @@ import org.springframework.web.reactive.function.client.WebClientResponseExcepti
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
+import reactor.netty.tcp.ProxyProvider.Proxy;
import reactor.netty.tcp.TcpClient;
/**
@@ -54,19 +56,12 @@ public class AsyncRestClient {
private final String baseUrl;
private static final AtomicInteger sequenceNumber = new AtomicInteger();
private final SslContext sslContext;
+ private final HttpProxyConfig httpProxyConfig;
- /**
- * Note that only http (not https) will work when this constructor is used.
- *
- * @param baseUrl
- */
- public AsyncRestClient(String baseUrl) {
- this(baseUrl, null);
- }
-
- public AsyncRestClient(String baseUrl, SslContext sslContext) {
+ public AsyncRestClient(String baseUrl, @Nullable SslContext sslContext, @Nullable HttpProxyConfig httpProxyConfig) {
this.baseUrl = baseUrl;
this.sslContext = sslContext;
+ this.httpProxyConfig = httpProxyConfig;
}
public Mono<ResponseEntity<String>> postForEntity(String uri, @Nullable String body) {
@@ -200,27 +195,32 @@ public class AsyncRestClient {
}
}
- private TcpClient createTcpClientSecure(SslContext sslContext) {
- return TcpClient.create(ConnectionProvider.newConnection()) //
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
- .secure(c -> c.sslContext(sslContext)) //
- .doOnConnected(connection -> {
- connection.addHandlerLast(new ReadTimeoutHandler(30));
- connection.addHandlerLast(new WriteTimeoutHandler(30));
- });
+ private boolean isHttpProxyConfigured() {
+ return httpProxyConfig != null && httpProxyConfig.httpProxyPort() > 0
+ && !httpProxyConfig.httpProxyHost().isEmpty();
}
- private TcpClient createTcpClientInsecure() {
- return TcpClient.create(ConnectionProvider.newConnection()) //
+ private TcpClient createTcpClient() {
+ TcpClient client = TcpClient.create(ConnectionProvider.newConnection()) //
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(30));
connection.addHandlerLast(new WriteTimeoutHandler(30));
});
+ if (this.sslContext != null) {
+ client = client.secure(c -> c.sslContext(sslContext));
+ }
+ if (isHttpProxyConfigured()) {
+ client = client.proxy(proxy -> {
+ proxy.type(Proxy.HTTP).host(httpProxyConfig.httpProxyHost()).port(httpProxyConfig.httpProxyPort());
+ });
+ }
+ return client;
}
private WebClient createWebClient(String baseUrl, TcpClient tcpClient) {
HttpClient httpClient = HttpClient.from(tcpClient);
+
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() //
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) //
@@ -235,13 +235,8 @@ public class AsyncRestClient {
private Mono<WebClient> getWebClient() {
if (this.webClient == null) {
try {
- if (this.sslContext != null) {
- TcpClient tcpClient = createTcpClientSecure(sslContext);
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- } else {
- TcpClient tcpClient = createTcpClientInsecure();
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- }
+ TcpClient tcpClient = createTcpClient();
+ this.webClient = createWebClient(this.baseUrl, tcpClient);
} catch (Exception e) {
logger.error("Could not create WebClient {}", e.getMessage());
return Mono.error(e);
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientFactory.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientFactory.java
index 5b88fce4..b5590cc2 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientFactory.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientFactory.java
@@ -42,6 +42,7 @@ import java.util.stream.Collectors;
import javax.net.ssl.KeyManagerFactory;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig.HttpProxyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
@@ -49,29 +50,43 @@ import org.springframework.util.ResourceUtils;
/**
* Factory for a generic reactive REST client.
*/
+@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
public class AsyncRestClientFactory {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final SslContextFactory sslContextFactory;
+ private final HttpProxyConfig httpProxyConfig;
public AsyncRestClientFactory(WebClientConfig clientConfig) {
if (clientConfig != null) {
this.sslContextFactory = new CachingSslContextFactory(clientConfig);
+ this.httpProxyConfig = clientConfig.httpProxyConfig();
} else {
+ logger.warn("HTTPS will not work");
this.sslContextFactory = null;
+ this.httpProxyConfig = null;
}
}
+ public AsyncRestClient createRestClientNoHttpProxy(String baseUrl) {
+ return createRestClient(baseUrl, false);
+ }
+
public AsyncRestClient createRestClient(String baseUrl) {
+ return createRestClient(baseUrl, true);
+ }
+
+ private AsyncRestClient createRestClient(String baseUrl, boolean useHttpProxy) {
if (this.sslContextFactory != null) {
try {
- return new AsyncRestClient(baseUrl, this.sslContextFactory.createSslContext());
+ return new AsyncRestClient(baseUrl, this.sslContextFactory.createSslContext(),
+ useHttpProxy ? httpProxyConfig : null);
} catch (Exception e) {
String exceptionString = e.toString();
logger.error("Could not init SSL context, reason: {}", exceptionString);
}
}
- return new AsyncRestClient(baseUrl);
+ return new AsyncRestClient(baseUrl, null, httpProxyConfig);
}
private class SslContextFactory {
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java
index 3b581b63..448b7b61 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClient.java
@@ -81,7 +81,8 @@ public class CcsdkA1AdapterClient implements A1Client {
* Constructor that creates the REST client to use.
*
* @param protocolType the southbound protocol of the controller. Supported
- * protocols are CCSDK_A1_ADAPTER_STD_V1_1, CCSDK_A1_ADAPTER_OSC_V1 and
+ * protocols are CCSDK_A1_ADAPTER_STD_V1_1,
+ * CCSDK_A1_ADAPTER_OSC_V1 and
* CCSDK_A1_ADAPTER_STD_V2_0_0 with
* @param ricConfig the configuration of the Near-RT RIC to communicate
* with
@@ -92,14 +93,15 @@ public class CcsdkA1AdapterClient implements A1Client {
public CcsdkA1AdapterClient(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
AsyncRestClientFactory restClientFactory) {
this(protocolType, ricConfig, controllerConfig,
- restClientFactory.createRestClient(controllerConfig.baseUrl() + "/restconf/operations"));
+ restClientFactory.createRestClientNoHttpProxy(controllerConfig.baseUrl() + "/restconf/operations"));
}
/**
* Constructor where the REST client to use is provided.
*
* @param protocolType the southbound protocol of the controller. Supported
- * protocols are CCSDK_A1_ADAPTER_STD_V1_1, CCSDK_A1_ADAPTER_OSC_V1 and
+ * protocols are CCSDK_A1_ADAPTER_STD_V1_1,
+ * CCSDK_A1_ADAPTER_OSC_V1 and
* CCSDK_A1_ADAPTER_STD_V2_0_0 with
* @param ricConfig the configuration of the Near-RT RIC to communicate
* with
@@ -108,7 +110,7 @@ public class CcsdkA1AdapterClient implements A1Client {
*
* @throws IllegalArgumentException when the protocolType is illegal.
*/
- public CcsdkA1AdapterClient(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
+ CcsdkA1AdapterClient(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
AsyncRestClient restClient) {
if (A1ProtocolType.CCSDK_A1_ADAPTER_STD_V1_1.equals(protocolType) //
|| A1ProtocolType.CCSDK_A1_ADAPTER_OSC_V1.equals(protocolType) //
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
index 65c6daa3..d6dc3975 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java
@@ -29,6 +29,7 @@ import javax.validation.constraints.NotEmpty;
import lombok.Getter;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig.HttpProxyConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -64,6 +65,12 @@ public class ApplicationConfig {
@Value("${app.webclient.trust-store}")
private String sslTrustStore = "";
+ @Value("${app.webclient.http.proxy-host}")
+ private String httpProxyHost = "";
+
+ @Value("${app.webclient.http.proxy-port}")
+ private int httpProxyPort = 0;
+
private Map<String, RicConfig> ricConfigs = new HashMap<>();
@Getter
@@ -79,6 +86,11 @@ public class ApplicationConfig {
}
public WebClientConfig getWebClientConfig() {
+ HttpProxyConfig httpProxyConfig = ImmutableHttpProxyConfig.builder() //
+ .httpProxyHost(this.httpProxyHost) //
+ .httpProxyPort(this.httpProxyPort) //
+ .build();
+
return ImmutableWebClientConfig.builder() //
.keyStoreType(this.sslKeyStoreType) //
.keyStorePassword(this.sslKeyStorePassword) //
@@ -87,6 +99,7 @@ public class ApplicationConfig {
.isTrustStoreUsed(this.sslTrustStoreUsed) //
.trustStore(this.sslTrustStore) //
.trustStorePassword(this.sslTrustStorePassword) //
+ .httpProxyConfig(httpProxyConfig) //
.build();
}
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientConfig.java
index ef7bd87c..beb6e51f 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientConfig.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientConfig.java
@@ -42,4 +42,13 @@ public interface WebClientConfig {
public String trustStore();
+ @Value.Immutable
+ public interface HttpProxyConfig {
+ public String httpProxyHost();
+
+ public int httpProxyPort();
+ }
+
+ public HttpProxyConfig httpProxyConfig();
+
}
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/ServiceCallbacks.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/ServiceCallbacks.java
index d6286eed..f9e446e4 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/ServiceCallbacks.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/ServiceCallbacks.java
@@ -48,7 +48,7 @@ public class ServiceCallbacks {
private final AsyncRestClient restClient;
public ServiceCallbacks(AsyncRestClientFactory restClientFactory) {
- this.restClient = restClientFactory.createRestClient("");
+ this.restClient = restClientFactory.createRestClientNoHttpProxy("");
}
public void notifyServicesRicSynchronized(Ric ric, Services services) {
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
index 8dd2df61..ec776042 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
@@ -97,7 +97,8 @@ public class PolicyController {
private static Gson gson = new GsonBuilder() //
.create(); //
- @GetMapping(path = "/v2/policy-types/{policytype_id:.+}", produces = MediaType.APPLICATION_JSON_VALUE)
+ @GetMapping(path = Consts.V2_API_ROOT + "/policy-types/{policytype_id:.+}",
+ produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Returns a policy type definition")
@ApiResponses(value = { //
@ApiResponse(code = 200, message = "Policy type", response = PolicyTypeInfo.class), //
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java
index f948e5f5..3a06e71f 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/dmaap/DmaapMessageConsumer.java
@@ -182,7 +182,7 @@ public class DmaapMessageConsumer {
protected Mono<String> getFromMessageRouter(String topicUrl) {
logger.trace("getFromMessageRouter {}", topicUrl);
- AsyncRestClient c = restClientFactory.createRestClient("");
+ AsyncRestClient c = restClientFactory.createRestClientNoHttpProxy("");
return c.get(topicUrl);
}
@@ -229,9 +229,9 @@ public class DmaapMessageConsumer {
private DmaapMessageHandler getDmaapMessageHandler() {
if (this.dmaapMessageHandler == null) {
String pmsBaseUrl = "http://localhost:" + this.localServerHttpPort;
- AsyncRestClient pmsClient = restClientFactory.createRestClient(pmsBaseUrl);
+ AsyncRestClient pmsClient = restClientFactory.createRestClientNoHttpProxy(pmsBaseUrl);
AsyncRestClient producer =
- restClientFactory.createRestClient(this.applicationConfig.getDmaapProducerTopicUrl());
+ restClientFactory.createRestClientNoHttpProxy(this.applicationConfig.getDmaapProducerTopicUrl());
this.dmaapMessageHandler = new DmaapMessageHandler(producer, pmsClient);
}
return this.dmaapMessageHandler;
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientTest.java
index 36bbda57..2e583f65 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClientTest.java
@@ -58,7 +58,7 @@ class AsyncRestClientTest {
InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);
Loggers.useJdkLoggers();
mockWebServer = new MockWebServer();
- clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString());
+ clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString(), null, null);
}
@AfterAll
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClientTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClientTest.java
index aad1ed02..985ce558 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClientTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/CcsdkA1AdapterClientTest.java
@@ -85,7 +85,7 @@ class CcsdkA1AdapterClientTest {
@Test
void createClientWithWrongProtocol_thenErrorIsThrown() {
assertThrows(IllegalArgumentException.class, () -> {
- new CcsdkA1AdapterClient(A1ProtocolType.STD_V1_1, null, null, new AsyncRestClient("", null));
+ new CcsdkA1AdapterClient(A1ProtocolType.STD_V1_1, null, null, new AsyncRestClient("", null, null));
});
}
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ApplicationTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ApplicationTest.java
index 551ed599..b5164889 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ApplicationTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v1/ApplicationTest.java
@@ -720,10 +720,11 @@ class ApplicationTest {
.isTrustStoreUsed(useTrustValidation) //
.trustStore(config.trustStore()) //
.trustStorePassword(config.trustStorePassword()) //
+ .httpProxyConfig(config.httpProxyConfig()) //
.build();
AsyncRestClientFactory f = new AsyncRestClientFactory(config);
- return f.createRestClient(baseUrl());
+ return f.createRestClientNoHttpProxy(baseUrl());
}
private AsyncRestClient restClient() {
diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java
index a0cb2af8..5e089a0b 100644
--- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java
+++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java
@@ -790,10 +790,11 @@ class ApplicationTest {
.isTrustStoreUsed(useTrustValidation) //
.trustStore(config.trustStore()) //
.trustStorePassword(config.trustStorePassword()) //
+ .httpProxyConfig(config.httpProxyConfig()) //
.build();
AsyncRestClientFactory f = new AsyncRestClientFactory(config);
- return f.createRestClient(baseUrl);
+ return f.createRestClientNoHttpProxy(baseUrl);
}