aboutsummaryrefslogtreecommitdiffstats
path: root/sdclient/discovery-service/src/main/java
diff options
context:
space:
mode:
authorHuabingZhao <zhao.huabing@zte.com.cn>2017-07-04 05:15:15 +0000
committerHuabingZhao <zhao.huabing@zte.com.cn>2017-07-04 05:51:17 +0000
commit5353f7df61d16d6624ba033627a7d09160fb679c (patch)
treec5dd805b7c1655589a0edaf0a6a7d54e78fec539 /sdclient/discovery-service/src/main/java
parenta3fa8cc2c6fa2883bc88a8244cbce5cacfd4fadf (diff)
migrate discovery source codes from OPEN-O
Change-Id: I65396f0ed5f85542e8b17b509fc30073bf7f959e Signed-off-by: HuabingZhao <zhao.huabing@zte.com.cn>
Diffstat (limited to 'sdclient/discovery-service/src/main/java')
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java140
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java86
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java167
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java74
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java108
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java65
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java38
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java84
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java39
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java154
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java51
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java87
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java46
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java149
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java111
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java106
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java95
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java147
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java194
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java28
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java28
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java19
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java58
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java395
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java66
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java84
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java214
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java1946
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java875
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java281
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java41
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java246
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java41
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java229
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java69
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java79
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java265
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java477
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java34
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java47
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java70
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java38
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java20
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java250
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java530
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java28
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java22
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java99
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java246
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java33
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java34
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java140
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java153
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java218
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java171
-rw-r--r--sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java117
56 files changed, 9632 insertions, 0 deletions
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java
new file mode 100644
index 0000000..7c9185a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient;
+
+import org.onap.msb.sdclient.resources.MicroServiceResource;
+import org.onap.msb.sdclient.wrapper.ConsulClientApp;
+import org.onap.msb.sdclient.wrapper.PublishAddressWrapper;
+import org.onap.msb.sdclient.wrapper.util.ConfigUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import io.dropwizard.Application;
+import io.dropwizard.server.SimpleServerFactory;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.jaxrs.listing.ApiListingResource;
+
+public class DiscoverApp extends Application<DiscoverAppConfig> {
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(DiscoverApp.class);
+
+ public static void main(String[] args) throws Exception {
+ new DiscoverApp().run(args);
+
+ }
+
+ private DiscoverAppConfig config;
+
+ @Override
+ public String getName() {
+ return " MicroService Bus ";
+ }
+
+ @Override
+ public void initialize(Bootstrap<DiscoverAppConfig> bootstrap) {
+// bootstrap.addBundle(new AssetsBundle("/iui-metrics",
+// "/iui/microservices/metrics", "index.html", "iui-metrics"));
+// bootstrap.addBundle(new AssetsBundle("/iui-discover",
+// "/iui/microservices", "index.html", "iui-microservices"));
+// bootstrap.addBundle(new AssetsBundle("/iui-discover", "/iui",
+// "index.html", "iui"));
+
+
+ }
+
+ @Override
+ public void run(DiscoverAppConfig configuration, Environment environment) {
+
+ environment.jersey().register(new MicroServiceResource());
+
+ config=configuration;
+
+ initSwaggerConfig(environment, configuration);
+
+ ConfigUtil.getInstance().initConsulClientInfo(configuration);
+
+ initApiGateWayServiceListen();
+
+ ConfigUtil.getInstance().initTCP_UDP_portRange();
+
+ ConfigUtil.getInstance().initConsulRegisterMode(configuration);
+
+ }
+
+
+
+ private void initSwaggerConfig(Environment environment,
+ DiscoverAppConfig configuration) {
+
+ environment.jersey().register(new ApiListingResource());
+ environment.getObjectMapper().setSerializationInclusion(
+ JsonInclude.Include.NON_NULL);
+
+ BeanConfig config = new BeanConfig();
+ config.setTitle("Service Discovery RESTful API");
+ config.setVersion("1.0.0");
+ config.setResourcePackage("org.onap.msb.sdclient.resources");
+ // 设置swagger里面访问rest api时的basepath
+ SimpleServerFactory simpleServerFactory = (SimpleServerFactory) configuration
+ .getServerFactory();
+ // 必须以"/"开头,结尾可有可无"/"
+ String basePath = simpleServerFactory.getApplicationContextPath();
+ String rootPath = simpleServerFactory.getJerseyRootPath();
+
+ rootPath = rootPath.substring(0, rootPath.indexOf("/*"));
+
+ basePath = basePath.equals("/") ? rootPath : (new StringBuilder())
+ .append(basePath).append(rootPath).toString();
+
+ LOGGER.info("getApplicationContextPath: " + basePath);
+ config.setBasePath(basePath);
+ config.setScan(true);
+ }
+
+
+
+
+
+
+
+
+
+ /**
+ * @Title initApiGateWayServiceListen
+ * @Description TODO(开启对consul中ApiGateWay服务的监听和缓存)
+ * @return void
+ */
+ private void initApiGateWayServiceListen(){
+
+ String[] consulAddress= ConfigUtil.getInstance().getConsulAddress().split(":");
+ ConsulClientApp consulClientApp = new ConsulClientApp(consulAddress[0],Integer.parseInt(consulAddress[1]));
+
+ PublishAddressWrapper.getInstance().setConsulClientApp(consulClientApp);
+ // 监听服务变化
+ //consulClientApp.startHealthNodeListen(DiscoverUtil.APIGATEWAY_SERVINCE_ALL);
+ //LOGGER.info("start monitor ApiGateWay service--" + DiscoverUtil.CONSUL_ADDRESSS+"--"+DiscoverUtil.APIGATEWAY_SERVINCE);
+
+ }
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java
new file mode 100644
index 0000000..96576fa
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient;
+
+import io.dropwizard.Configuration;
+
+import javax.validation.Valid;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class DiscoverAppConfig extends Configuration {
+ @NotEmpty
+ private String defaultWorkspace = "discover-works";
+
+ @NotEmpty
+ private String defaultName = "discover-service";
+
+
+ @Valid
+ private String consulAdderss;
+
+ @Valid
+ private String consulRegisterMode;
+
+
+ @JsonProperty
+ public String getConsulRegisterMode() {
+ return consulRegisterMode;
+ }
+
+ @JsonProperty
+ public void setConsulRegisterMode(String consulRegisterMode) {
+ this.consulRegisterMode = consulRegisterMode;
+ }
+
+ @JsonProperty
+ public String getDefaultWorkspace() {
+ return defaultWorkspace;
+ }
+
+ @JsonProperty
+ public void setDefaultWorkspace(String defaultWorkspace) {
+ this.defaultWorkspace = defaultWorkspace;
+ }
+
+ @JsonProperty
+ public String getDefaultName() {
+ return defaultName;
+ }
+
+ @JsonProperty
+ public void setDefaultName(String name) {
+ this.defaultName = name;
+ }
+
+ @JsonProperty
+ public String getConsulAdderss() {
+ return consulAdderss;
+ }
+
+ @JsonProperty
+ public void setConsulAdderss(String consulAdderss) {
+ this.consulAdderss = consulAdderss;
+ }
+
+
+
+
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java
new file mode 100644
index 0000000..f85e583
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java
@@ -0,0 +1,167 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AgentService implements Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("ID")
+ private String id;
+
+ @JsonProperty("Name")
+ private String name;
+
+ @JsonProperty("Tags")
+ private List<String> tags;
+
+ @JsonProperty("Address")
+ private String address;
+
+ @JsonProperty("Port")
+ private int port;
+
+ @JsonProperty("Check")
+ @JsonInclude(Include.NON_EMPTY)
+ private Check check;
+
+ @JsonInclude(Include.NON_EMPTY)
+ public class Check{
+
+ @JsonProperty("HTTP")
+ private String http;
+
+ @JsonProperty("TCP")
+ private String tcp;
+
+ @JsonProperty("TTL")
+ private String ttl;
+
+ @JsonProperty("Interval")
+ private String interval;
+
+ @JsonProperty("Timeout")
+ private String timeout;
+
+
+ private String status="passing";
+
+ public String getTimeout() {
+ return timeout;
+ }
+ public void setTimeout(String timeout) {
+ this.timeout = timeout;
+ }
+
+ public String getHttp() {
+ return http;
+ }
+ public void setHttp(String http) {
+ this.http = http;
+ }
+ public String getTcp() {
+ return tcp;
+ }
+ public void setTcp(String tcp) {
+ this.tcp = tcp;
+ }
+ public String getTtl() {
+ return ttl;
+ }
+ public void setTtl(String ttl) {
+ this.ttl = ttl;
+ }
+ public String getInterval() {
+ return interval;
+ }
+ public void setInterval(String interval) {
+ this.interval = interval;
+ }
+ public String getStatus() {
+ return status;
+ }
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+
+ public void setTags(List<String> tags) {
+ this.tags = tags;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public Check getCheck() {
+ return check;
+ }
+
+ public void setCheck(Check check) {
+ this.check = check;
+ }
+
+ public Check createCheck(){
+ return new Check();
+
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java
new file mode 100644
index 0000000..307fbcb
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CatalogNode implements Serializable{
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("Node")
+ private String node=DiscoverUtil.EXTERNAL_NODE_NAME;
+
+ @JsonProperty("Address")
+ private String address="127.0.0.1";
+
+ @JsonProperty("Service")
+ private ConsulService service;
+
+ public String getNode() {
+ return node;
+ }
+
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public ConsulService getService() {
+ return service;
+ }
+
+ public void setService(ConsulService service) {
+ this.service = service;
+ }
+
+ public CatalogNode(){
+
+ }
+
+ public CatalogNode(ConsulService service){
+ this.service = service;
+ }
+
+
+}
+
+
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java
new file mode 100644
index 0000000..dd4e2d6
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CatalogService implements Serializable{
+ private static final long serialVersionUID = 1L;
+ @JsonProperty("Node")
+ private String node;
+
+ @JsonProperty("Address")
+ private String address;
+
+ @JsonProperty("ServiceName")
+ private String serviceName;
+
+ @JsonProperty("ServiceID")
+ private String serviceId;
+
+ @JsonProperty("ServiceAddress")
+ private String serviceAddress;
+
+ @JsonProperty("ServicePort")
+ private int servicePort;
+
+ @JsonProperty("ServiceTags")
+ private List<String> serviceTags;
+
+ public String getNode() {
+ return node;
+ }
+
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(String serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ public String getServiceAddress() {
+ return serviceAddress;
+ }
+
+ public void setServiceAddress(String serviceAddress) {
+ this.serviceAddress = serviceAddress;
+ }
+
+ public int getServicePort() {
+ return servicePort;
+ }
+
+ public void setServicePort(int servicePort) {
+ this.servicePort = servicePort;
+ }
+
+ public List<String> getServiceTags() {
+ return serviceTags;
+ }
+
+ public void setServiceTags(List<String> serviceTags) {
+ this.serviceTags = serviceTags;
+ }
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java
new file mode 100644
index 0000000..ffa4683
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Check implements Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("CheckID")
+ private String checkID;
+
+ @JsonProperty("Name")
+ private String name;
+
+ @JsonProperty("Status")
+ private String status;
+
+ public String getCheckID() {
+ return checkID;
+ }
+
+ public void setCheckID(String checkID) {
+ this.checkID = checkID;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java
new file mode 100644
index 0000000..0839e8f
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.math.BigInteger;
+
+public class ConsulResponse<T> {
+
+ private final T response;
+ private final BigInteger index;
+
+ public ConsulResponse(T response, BigInteger index) {
+ this.response = response;
+ this.index = index;
+ }
+
+ public BigInteger getIndex() {
+ return index;
+ }
+ public T getResponse() {
+ return response;
+ }
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java
new file mode 100644
index 0000000..5b5763c
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ConsulService implements Serializable{
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("ID")
+ private String id;
+
+ @JsonProperty("Service")
+ private String service;
+
+ @JsonProperty("Tags")
+ private List<String> tags;
+
+ @JsonProperty("Address")
+ private String address;
+
+ @JsonProperty("Port")
+ private int port;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getService() {
+ return service;
+ }
+
+ public void setService(String service) {
+ this.service = service;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+
+ public void setTags(List<String> tags) {
+ this.tags = tags;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java
new file mode 100644
index 0000000..6efeb04
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+public class CustomDateSerializer extends JsonSerializer<Date> {
+
+ @Override
+ public void serialize(Date value,
+ JsonGenerator jsonGenerator,
+ SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
+ jsonGenerator.writeString(sdf.format(value));
+ }
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java
new file mode 100644
index 0000000..f952ee5
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class HealthService implements Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("Node")
+ private Node node;
+
+ @JsonProperty("Service")
+ private Service service;
+
+ @JsonProperty("Checks")
+ private List<Check> checks;
+
+
+ public Node getNode() {
+ return node;
+ }
+
+ public void setNode(Node node) {
+ this.node = node;
+ }
+
+ public Service getService() {
+ return service;
+ }
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ public List<Check> getChecks() {
+ return checks;
+ }
+
+ public void setChecks(List<Check> checks) {
+ this.checks = checks;
+ }
+
+
+
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public class Service{
+ @JsonProperty("ID")
+ private String id;
+
+ @JsonProperty("Service")
+ private String service;
+
+ @JsonProperty("Tags")
+ private List<String> tags;
+
+ @JsonProperty("Address")
+ private String address;
+
+ @JsonProperty("Port")
+ private String port;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getService() {
+ return service;
+ }
+
+ public void setService(String service) {
+ this.service = service;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+
+ public void setTags(List<String> tags) {
+ this.tags = tags;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ }
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public class Node{
+
+ @JsonProperty("Node")
+ private String node;
+
+ @JsonProperty("Address")
+ private String address;
+
+ public String getNode() {
+ return node;
+ }
+
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java
new file mode 100644
index 0000000..4fca0ed
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+
+public class KeyVaulePair implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String key;
+ private String value;
+
+ public String getKey() {
+ return key;
+ }
+ public void setKey(String key) {
+ this.key = key;
+ }
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public KeyVaulePair(){
+
+ }
+
+ public KeyVaulePair(String key,String value){
+ this.key=key;
+ this.value=value;
+
+ }
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java
new file mode 100644
index 0000000..ec5c52a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+
+
+public class MicroServiceFullInfo extends Service<NodeInfo> implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ // 状态 0:不可用,待审核 1:可用,审核通过 2:审核失败
+ private String status = "1";
+
+ private boolean is_manual=false; //手动注册:true; 自动注册:false
+
+ private Set<NodeInfo> nodes;
+
+
+ public Set<NodeInfo> getNodes() {
+ return nodes;
+ }
+
+ public void setNodes(Set<NodeInfo> nodes) {
+ this.nodes = nodes;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+
+ public boolean isIs_manual() {
+ return is_manual;
+ }
+
+ public void setIs_manual(boolean is_manual) {
+ this.is_manual = is_manual;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getServiceName(),getVersion(),getProtocol(),getNamespace(),getUrl(),getVisualRange(),nodes);
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof MicroServiceFullInfo)
+ {
+ MicroServiceFullInfo that = (MicroServiceFullInfo)other;
+ return Objects.equal(getServiceName(), that.getServiceName())
+ && Objects.equal(getVersion(), that.getVersion())
+ && Objects.equal(getProtocol(), that.getProtocol())
+ && Objects.equal(getNamespace(), that.getNamespace())
+ && Objects.equal(getUrl(), that.getUrl())
+ && Objects.equal(getVisualRange(), that.getVisualRange())
+ && Objects.equal(nodes.hashCode(), that.nodes.hashCode());
+ } else
+ {
+ return false;
+ }
+ }
+
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java
new file mode 100644
index 0000000..d5e8296
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * @ClassName: MicroServiceInfo Bean
+ * @Description:P2PRouteInfo信息实体类
+ * @author 10188044
+ * @date 2016-1-19
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MicroServiceInfo extends Service<Node> implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private Set<Node> nodes;
+
+ public Set<Node> getNodes() {
+ return nodes;
+ }
+
+ public void setNodes(Set<Node> nodes) {
+ this.nodes = nodes;
+ }
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java
new file mode 100644
index 0000000..8727248
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java
@@ -0,0 +1,149 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Node implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(example = "127.0.0.1",required = true)
+ private String ip;
+
+ @ApiModelProperty(example = "80", required = true)
+ private String port;
+
+
+ //负载均衡策略参数
+ @ApiModelProperty(value = "lb node params", allowableValues = "weight,max_fails,fail_timeout", example = "weight=5,max_fails=3,fail_timeout=30s")
+ private String lb_server_params;
+
+ //健康检查参数
+ @ApiModelProperty(value = "health check type", allowableValues = "TTL,HTTP,TCP", example = "TTL")
+ private String checkType="";
+
+ @ApiModelProperty(value = "health check URL,applies only to TCP or HTTP", example = "http://localhost:5000/health")
+ private String checkUrl="";
+
+ @ApiModelProperty(value = "TCP or HTTP health check Interval,Unit: second", example = "10s")
+ private String checkInterval;
+
+ @ApiModelProperty(value = "TCP or HTTP health check TimeOut,Unit: second", example = "10s")
+ private String checkTimeOut;
+
+ @ApiModelProperty(value = "TTL health check Interval,Unit: second", example = "10s")
+ private String ttl;
+
+
+ @ApiModelProperty(value = "Instance HA_role", allowableValues = "active,standby", example = "active")
+ private String ha_role="";
+
+
+
+
+
+ public String getHa_role() {
+ return ha_role;
+ }
+
+ public void setHa_role(String ha_role) {
+ this.ha_role = ha_role;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public String getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(String ttl) {
+ this.ttl = ttl;
+ }
+
+ public Node(){
+
+ }
+
+ public Node(String ip,String port){
+ this.ip = ip;
+ this.port = port;
+ }
+
+ public String getLb_server_params() {
+ return lb_server_params;
+ }
+
+ public void setLb_server_params(String lb_server_params) {
+ this.lb_server_params = lb_server_params;
+ }
+
+
+ public String getCheckType() {
+ return checkType;
+ }
+
+ public void setCheckType(String checkType) {
+ this.checkType = checkType;
+ }
+
+ public String getCheckUrl() {
+ return checkUrl;
+ }
+
+ public void setCheckUrl(String checkUrl) {
+ this.checkUrl = checkUrl;
+ }
+
+ public String getCheckInterval() {
+ return checkInterval;
+ }
+
+ public void setCheckInterval(String checkInterval) {
+ this.checkInterval = checkInterval;
+ }
+
+ public String getCheckTimeOut() {
+ return checkTimeOut;
+ }
+
+ public void setCheckTimeOut(String checkTimeOut) {
+ this.checkTimeOut = checkTimeOut;
+ }
+
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java
new file mode 100644
index 0000000..91b6206
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+
+public class NodeAddress implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(required = true)
+ private String ip;
+
+ @ApiModelProperty(required = true)
+ private String port;
+
+
+
+ private PropertyChangeSupport changes = new PropertyChangeSupport(this);
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public NodeAddress(String ip,String port){
+ this.ip=ip;
+ this.port=port;
+ }
+
+ public void setIPandPort(String ip,String port){
+ String oldAddress = this.ip+":"+this.port;
+ String newAddress = ip+":"+port;
+ this.ip=ip;
+ this.port=port;
+
+ changes.firePropertyChange("ip", oldAddress, newAddress);
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ changes.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ changes.removePropertyChangeListener(listener);
+ }
+
+ public NodeAddress(){
+
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof NodeAddress)
+ {
+ NodeAddress that = (NodeAddress)other;
+ return Objects.equal(ip, that.ip) && Objects.equal(port, that.port);
+ } else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ip, port);
+ }
+
+ @Override
+ public String toString(){
+ return this.ip+":"+this.port;
+ }
+
+
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java
new file mode 100644
index 0000000..950c0d8
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.base.Objects;
+
+public class NodeInfo extends Node {
+
+ private static final long serialVersionUID = 8955786461351557306L;
+
+ private String nodeId; //node唯一标识
+
+ private String status; //实例健康检查状态
+
+
+ @JsonSerialize(using = CustomDateSerializer.class)
+ private Date expiration;
+
+ @JsonSerialize(using = CustomDateSerializer.class)
+ private Date created_at;
+
+ @JsonSerialize(using = CustomDateSerializer.class)
+ private Date updated_at;
+
+
+
+ public Date getExpiration() {
+ return expiration;
+ }
+
+ public void setExpiration(Date expiration) {
+ this.expiration = expiration;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public void setCreated_at(Date created_at) {
+ this.created_at = created_at;
+ }
+
+ public Date getUpdated_at() {
+ return updated_at;
+ }
+
+ public void setUpdated_at(Date updated_at) {
+ this.updated_at = updated_at;
+ }
+
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ public void setNodeId(String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(getIp(),getPort(),getHa_role(),status );
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof NodeInfo)
+ {
+ NodeInfo that = (NodeInfo)other;
+ return Objects.equal(getIp(), that.getIp())
+ && Objects.equal(getPort(), that.getPort());
+ } else
+ {
+ return false;
+ }
+ }
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java
new file mode 100644
index 0000000..ef49b31
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+import com.google.common.base.Objects;
+
+public class PublishAddress implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value = "Service Publish IP")
+ private String ip;
+
+ @ApiModelProperty(value = "Service Publish Port", required = true)
+ private String port;
+
+ @ApiModelProperty(value = "Service Publish URL,start with /",example = "/api/serviceName/v1", required = true)
+ private String publish_url;
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public PublishAddress(){
+
+ }
+
+ public PublishAddress(String ip,String port,String publish_url){
+ this.ip=ip;
+ this.port=port;
+ this.publish_url = publish_url;
+ }
+
+ public String getPublish_url() {
+ return publish_url;
+ }
+
+ public void setPublish_url(String publish_url) {
+ this.publish_url = publish_url;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof PublishAddress)
+ {
+ PublishAddress that = (PublishAddress)other;
+ return Objects.equal(ip, that.ip) && Objects.equal(port, that.port)&& Objects.equal(publish_url, that.publish_url);
+ } else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ip, port,publish_url);
+ }
+
+ @Override
+ public String toString(){
+ return this.ip+":"+this.port+this.publish_url;
+ }
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java
new file mode 100644
index 0000000..03200c3
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth;
+
+import com.google.common.base.Objects;
+
+public class PublishFullAddress implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+
+ @ApiModelProperty(value = "Service Publish IP")
+ private String ip;
+
+ @ApiModelProperty(value = "Service Publish Domain")
+ private String domain;
+
+ @ApiModelProperty(value = "Service Publish Port", required = true)
+ private String port;
+
+ @ApiModelProperty(value = "Service Publish URL,start with /",example = "/api/serviceName/v1", required = true)
+ private String publish_url;
+
+ @ApiModelProperty(value = "[visual Range]outSystem:0,inSystem:1", allowableValues = "0,1", example = "1", required = true)
+ private String visualRange;
+
+ @ApiModelProperty(value = "Service Publish Protocol",allowableValues = "http,https",example = "https", required = true)
+ private String publish_protocol;
+
+ public String getPublish_protocol() {
+ return publish_protocol;
+ }
+
+ public void setPublish_protocol(String publish_protocol) {
+ this.publish_protocol = publish_protocol;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ public String getPublish_url() {
+ return publish_url;
+ }
+
+ public void setPublish_url(String publish_url) {
+ this.publish_url = publish_url;
+ }
+
+ public String getVisualRange() {
+ return visualRange;
+ }
+
+ public void setVisualRange(String visualRange) {
+ this.visualRange = visualRange;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public PublishFullAddress(){
+
+ }
+
+ public PublishFullAddress(String ip,String port,String publish_url,String visualRange,String publish_protocol ){
+ this.ip=ip;
+ this.port=port;
+ this.publish_url=publish_url;
+ this.visualRange=visualRange;
+ this.publish_protocol=publish_protocol;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof PublishFullAddress)
+ {
+ PublishFullAddress that = (PublishFullAddress)other;
+ return Objects.equal(ip, that.ip)
+ && Objects.equal(domain, that.domain)
+ && Objects.equal(port, that.port)
+ && Objects.equal(publish_url, that.publish_url)
+ && Objects.equal(visualRange, that.visualRange)
+ && Objects.equal(publish_protocol, that.publish_protocol);
+ } else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ip, domain,port,publish_url,visualRange,publish_protocol);
+ }
+
+ @Override
+ public String toString() {
+ // TODO Auto-generated method stub
+ if(StringUtils.isNotBlank(this.domain)){
+ return (new StringBuilder().append(this.publish_protocol).append("://").append(this.domain).append(":").append(this.port).append(this.publish_url)).toString();
+ }
+ else {
+ return (new StringBuilder().append(this.publish_protocol).append("://").append(this.ip).append(":").append(this.port).append(this.publish_url)).toString();
+ }
+
+ }
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java
new file mode 100644
index 0000000..9b382b7
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java
@@ -0,0 +1,194 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModelProperty;
+
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Service<T> implements Serializable {
+ private static final long serialVersionUID = 1L;
+ // 服务名
+ @ApiModelProperty(example = "test",required = true)
+ private String serviceName;
+ // 版本号
+ @ApiModelProperty(example = "v1", required = true)
+ private String version="";
+ // 服务url
+ @ApiModelProperty(value = "Target Service URL,start with /",example = "/api/serviceName/v1", required = true)
+ private String url="";
+
+ // 服务对应协议,比如REST、UI、MQ、FTP、SNMP、TCP、UDP
+ @ApiModelProperty(value = "Service Protocol", allowableValues = "REST,UI, HTTP, TCP,UDP", example = "HTTP",required = true)
+ private String protocol = "";
+
+ //服务的可见范围 0:系统间 1:系统内 ,可配置多个,以 |分隔
+ @ApiModelProperty(value = "[visual Range]interSystem:0,inSystem:1", allowableValues = "0,1", example = "1")
+ private String visualRange = "1";
+
+ //负载均衡策略类型
+ @ApiModelProperty(value = "lb policy", allowableValues = "round-robin,ip_hash", example = "ip_hash")
+ private String lb_policy;
+
+ //TCP/UDP协议监听端口
+ @ApiModelProperty(hidden = true)
+ private String publish_port;
+
+ //命名空间
+ private String namespace="";
+
+ //网络平面
+ @ApiModelProperty(hidden = true)
+ private String network_plane_type;
+
+ @ApiModelProperty(hidden = true)
+ private String host="";
+
+ @ApiModelProperty(hidden = true)
+ private String path="";
+
+
+
+
+ @ApiModelProperty(required = true)
+ private Set<T> nodes;
+
+ //服务自身属性的键值对
+ private List<KeyVaulePair> metadata;
+
+ //自定义标签
+ @ApiModelProperty(value = "custom labels", example = "key1:value1")
+ private List<String> labels;
+
+
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public List<String> getLabels() {
+ return labels;
+ }
+
+ public void setLabels(List<String> labels) {
+ this.labels = labels;
+ }
+
+ public Set<T> getNodes() {
+ return nodes;
+ }
+
+ public void setNodes(Set<T> nodes) {
+ this.nodes = nodes;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+ public String getVersion() {
+ return version;
+ }
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ public String getUrl() {
+ return url;
+ }
+ public void setUrl(String url) {
+ this.url = url;
+ }
+ public String getProtocol() {
+ return protocol;
+ }
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+
+
+ public List<KeyVaulePair> getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(List<KeyVaulePair> metadata) {
+ this.metadata = metadata;
+ }
+
+
+ public String getVisualRange() {
+ return visualRange;
+ }
+
+ public void setVisualRange(String visualRange) {
+ this.visualRange = visualRange;
+ }
+
+ public String getLb_policy() {
+ return lb_policy;
+ }
+
+ public void setLb_policy(String lb_policy) {
+ this.lb_policy = lb_policy;
+ }
+
+ public String getPublish_port() {
+ return publish_port;
+ }
+
+ public void setPublish_port(String publish_port) {
+ this.publish_port = publish_port;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getNetwork_plane_type() {
+ return network_plane_type;
+ }
+
+ public void setNetwork_plane_type(String network_plane_type) {
+ this.network_plane_type = network_plane_type;
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java
new file mode 100644
index 0000000..93a33a3
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core.exception;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+public class ExtendedInternalServerErrorException extends InternalServerErrorException {
+
+ public ExtendedInternalServerErrorException(final String message) {
+ super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type(MediaType.TEXT_PLAIN).build());
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java
new file mode 100644
index 0000000..4acf507
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.core.exception;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+public class ExtendedNotFoundException extends NotFoundException {
+
+ public ExtendedNotFoundException(final String message) {
+ super(Response.status(Response.Status.NOT_FOUND).entity(message).type(MediaType.TEXT_PLAIN).build());
+ }
+}
+
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java
new file mode 100644
index 0000000..ed7b632
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java
@@ -0,0 +1,19 @@
+package org.onap.msb.sdclient.core.exception;
+
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UnprocessableEntityException extends ClientErrorException{
+private static final long serialVersionUID = -8266622745725405656L;
+private static final Logger LOGGER = LoggerFactory.getLogger(UnprocessableEntityException.class);
+
+ public UnprocessableEntityException(final String message) {
+ super(Response.status(HttpStatus.SC_UNPROCESSABLE_ENTITY).entity(message).type(MediaType.TEXT_PLAIN).build());
+ LOGGER.warn(message);
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java
new file mode 100644
index 0000000..9596b4a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.health;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.wrapper.util.HttpClientUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.health.HealthCheck;
+
+public class ConsulLinkHealthCheck extends HealthCheck {
+
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(ConsulLinkHealthCheck.class);
+
+ private String CHECK_IP="127.0.0.1";
+ private String CHECK_PORT="8500";
+ private String CHECK_URL = "http://"+CHECK_IP+":"+CHECK_PORT+"/v1/status/leader";
+
+
+ @Override
+ protected Result check() throws Exception {
+ // TODO Auto-generated method stub
+
+ if(!StringUtils.isBlank(System.getenv("CONSUL_IP")))
+ {
+ CHECK_IP=System.getenv("CONSUL_IP");
+ CHECK_URL = "http://"+CHECK_IP+":"+CHECK_PORT+"/v1/status/leader";
+ LOGGER.info("check consul URL:"+CHECK_URL);
+ }
+
+ int resultStatus = HttpClientUtil.httpGetStatus(CHECK_URL);
+
+ if (resultStatus == 200) {
+ return Result.healthy();
+ } else {
+ return Result
+ .unhealthy("check consul link {} fail:{}",CHECK_URL,resultStatus);
+ }
+
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java
new file mode 100644
index 0000000..9b83d6d
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java
@@ -0,0 +1,395 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.resources;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.http.HttpStatus;
+import org.onap.msb.sdclient.core.ConsulResponse;
+import org.onap.msb.sdclient.core.MicroServiceFullInfo;
+import org.onap.msb.sdclient.core.MicroServiceInfo;
+import org.onap.msb.sdclient.core.NodeAddress;
+import org.onap.msb.sdclient.core.PublishAddress;
+import org.onap.msb.sdclient.core.PublishFullAddress;
+import org.onap.msb.sdclient.core.exception.ExtendedInternalServerErrorException;
+import org.onap.msb.sdclient.health.ConsulLinkHealthCheck;
+import org.onap.msb.sdclient.wrapper.ConsulServiceWrapper;
+import org.onap.msb.sdclient.wrapper.PublishAddressWrapper;
+import org.onap.msb.sdclient.wrapper.util.ConfigUtil;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.annotation.Timed;
+import com.codahale.metrics.health.HealthCheck;
+import com.codahale.metrics.health.HealthCheck.Result;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+@Path("/services")
+@Api(tags = { "Service Resource" })
+@Produces(MediaType.APPLICATION_JSON)
+public class MicroServiceResource {
+
+
+ @Context
+ UriInfo uriInfo; // actual uri info
+
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceResource.class);
+
+ @GET
+ @Path("/")
+ @ApiOperation(value = "get all microservices ", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class, responseContainer = "List")
+ @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get microservice List fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public List<MicroServiceFullInfo> getMicroService() {
+ return ConsulServiceWrapper.getInstance().getAllMicroServiceInstances();
+ }
+
+ @POST
+ @Path("/")
+ @ApiOperation(value = "add one microservice ", code = HttpStatus.SC_CREATED, response = MicroServiceFullInfo.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "add microservice fail", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable MicroServiceInfo JSON REQUEST", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Response addMicroService(
+ @ApiParam(value = "MicroServiceInfo Instance Info", required = true) MicroServiceInfo microServiceInfo,
+ @Context HttpServletRequest request,
+ @ApiParam(value = "createOrUpdate", required = false) @QueryParam("createOrUpdate") @DefaultValue("true") boolean createOrUpdate,
+ @ApiParam(value = "is_manual", required = false) @QueryParam("is_manual") @DefaultValue("false") boolean is_manual
+ ) {
+
+ String ip=DiscoverUtil.getRealIp(request);
+
+ try {
+ LOGGER.info("[POST REQUEST] Request IP:"+ip+",Request Param:[createOrUpdate]"+createOrUpdate+",Request Body:"+JacksonJsonUtil.beanToJson(microServiceInfo));
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ LOGGER.error("[POST REQUEST] beanToJson is wrong:"+e.getMessage());
+ }
+
+ MicroServiceFullInfo microServiceFullInfo =
+ ConsulServiceWrapper.getInstance().saveMicroServiceInstance(microServiceInfo,
+ createOrUpdate,ip,is_manual);
+ URI returnURI =
+ uriInfo.getAbsolutePathBuilder()
+ .path("/" + microServiceInfo.getServiceName() + "/version/"
+ + microServiceInfo.getVersion()).build();
+ return Response.created(returnURI).entity(microServiceFullInfo).build();
+ }
+
+
+
+ @GET
+ @Path("/{serviceName}/version/{version}/nodes")
+ @ApiOperation(value = "get one microservice ", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class, responseContainer = "List")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get microservice fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public List<MicroServiceFullInfo> getMicroServiceNodes(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "Format key:value,Multiple use ',' split", required = false) @QueryParam("labels") @DefaultValue("") String labels,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "if true then only query passing services", required = false) @QueryParam("ifPassStatus") @DefaultValue("true")boolean ifPassStatus
+ ) {
+
+ return ConsulServiceWrapper.getInstance().getMicroServiceForNodes(serviceName, version,ifPassStatus,labels,namespace);
+
+
+ }
+
+ @GET
+ @Path("/{serviceName}/version/{version}")
+ @ApiOperation(value = "get one microservice nodes", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get microservice fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Response getMicroService(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "Format key:value,Multiple use ',' split", required = false) @QueryParam("labels") @DefaultValue("") String labels,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "if true then only query passing services", required = false) @QueryParam("ifPassStatus") @DefaultValue("true")boolean ifPassStatus,
+ @ApiParam(value = "wait", required = false) @QueryParam("wait") @DefaultValue("") String wait,
+ @ApiParam(value = "index", required = false) @QueryParam("index") @DefaultValue("") String index) {
+
+
+ ConsulResponse<MicroServiceFullInfo> serviceResponse= ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version,ifPassStatus,wait,index,labels,namespace);
+ return Response.ok(serviceResponse.getResponse()).header("X-Consul-Index", serviceResponse.getIndex()).build();
+
+
+ }
+
+ @PUT
+ @Path("/{serviceName}/version/{version}")
+ @ApiOperation(value = "update one microservice by serviceName and version", code = HttpStatus.SC_CREATED, response = MicroServiceFullInfo.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update microservice fail", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable MicroServiceInfo JSON REQUEST", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Response updateMicroService(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "microservice Instance Info", required = true) MicroServiceInfo microServiceInfo,
+ @Context HttpServletRequest request,
+ @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol,
+ @ApiParam(value = "is_manual", required = false, hidden = true ) @QueryParam("is_manual") @DefaultValue("false") boolean is_manual) {
+
+ String ip=DiscoverUtil.getRealIp(request);
+ MicroServiceFullInfo microServiceFullInfo =ConsulServiceWrapper.getInstance().updateMicroServiceInstance(serviceName,version,namespace,microServiceInfo,ip,is_manual);
+ return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(microServiceFullInfo).build();
+
+ }
+
+ @PUT
+ @Path("/{serviceName}/version/{version}/ttl")
+ @ApiOperation(value = "passing one microservice health check by ttl", code = HttpStatus.SC_CREATED, response = NodeAddress.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "health check by ttl fail", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable CheckNode JSON REQUEST", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Response healthCheckbyTTL(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "CheckNode Instance Info", required = true) NodeAddress checkNode) {
+
+ ConsulServiceWrapper.getInstance().healthCheckbyTTL(serviceName,version,namespace,checkNode);
+ return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(checkNode).build();
+
+ }
+
+
+
+ @DELETE
+ @Path("/{serviceName}/version/{version}/nodes/{ip}/{port}")
+ @ApiOperation(value = "delete single node by serviceName and version and node", code = HttpStatus.SC_NO_CONTENT)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete node succeed "),
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "node not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete node fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public void deleteNode(
+ @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "ip") @PathParam("ip") String ip,
+ @ApiParam(value = "port") @PathParam("port") String port,
+ @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol) {
+ LOGGER.info("[DELETE NODE REQUEST] serviceName:"+serviceName+",version:"+version+",namespace:"+namespace+",protocol:"+protocol+",ip:"+ip+",port:"+port);
+ ConsulServiceWrapper.getInstance().deleteMicroServiceInstance(serviceName, version, namespace,ip,port);
+
+ }
+
+
+ @DELETE
+ @Path("/{serviceName}/version/{version}")
+ @ApiOperation(value = "delete one full microservice by serviceName and version", code = HttpStatus.SC_NO_CONTENT)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete microservice succeed "),
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete microservice fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public void deleteMicroService(
+ @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol) {
+
+ LOGGER.info("[DELETE REQUEST] serviceName:"+serviceName+",version:"+version+",namespace:"+namespace+",protocol:"+protocol);
+
+ ConsulServiceWrapper.getInstance().deleteMicroService(serviceName, version,namespace);
+
+ }
+
+
+
+
+
+
+
+
+ // @PUT
+ // @Path("/{serviceName}/version/{version}/status/{status}")
+ // @ApiOperation(value = "update one microservice's status by serviceName and version",
+ // response = RouteResult.class)
+ // @ApiResponses(value = {@ApiResponse(code = 500, message =
+ // "update microservice status error ")})
+ // @Produces(MediaType.APPLICATION_JSON)
+ // @Timed
+ // public RouteResult updateMicroServiceStatus(
+ // @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName")
+ // String serviceName,
+ // @ApiParam(value = "microservice version", required = false) @PathParam("version")
+ // @DefaultValue("") String version,
+ // @ApiParam(value = "microservice status", required = true) @PathParam("status") String status)
+ // {
+ //
+ // return MicroServiceWrapper.getInstance().updateMicroServiceStatus(serviceName, version,
+ // status);
+ //
+ // }
+
+
+ @GET
+ @Path("/{serviceName}/version/{version}/publishaddress")
+ @ApiOperation(value = "get one microservice's inner publishaddress", code = HttpStatus.SC_OK, response = PublishAddress.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "publishaddress not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get publishaddress fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public PublishAddress getPublishaddress(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "Waiting time,Scope: 5-300, unit: second", required = false) @QueryParam("wait") @DefaultValue("0") int wait
+ ) {
+
+
+ return PublishAddressWrapper.getInstance().getPublishaddress(serviceName, version,namespace,wait);
+
+
+ }
+
+ @GET
+ @Path("/apigatewayserviceinfo")
+ @ApiOperation(value = "get apigateway AddressInfo", code = HttpStatus.SC_OK,response = MicroServiceFullInfo.class, responseContainer = "List")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "apigateway ServiceInfo not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get apigateway ServiceInfo fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Set<MicroServiceFullInfo> getApigatewayServiceInfo(
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "visualRange", required = false) @QueryParam("visualRange") @DefaultValue("1") String visualRange) {
+
+
+ return PublishAddressWrapper.getInstance().getApigatewayServiceInfo(namespace, visualRange);
+
+
+ }
+
+ @GET
+ @Path("/{serviceName}/version/{version}/allpublishaddress")
+ @ApiOperation(value = "get one microservice's all publishaddress", code = HttpStatus.SC_OK, response = PublishFullAddress.class, responseContainer = "List")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "publishaddress not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get publishaddress fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public Set<PublishFullAddress> getAllPublishaddress(
+ @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName,
+ @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version,
+ @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace,
+ @ApiParam(value = "outSystem:0,inSystem:1,all:0|1(default)", required = false) @QueryParam("visualRange") @DefaultValue("0|1") String visualRange
+ ) {
+
+
+ return PublishAddressWrapper.getInstance().getAllPublishaddress(serviceName, version, namespace,visualRange);
+
+
+ }
+
+
+ @GET
+ @Path("/tcpudpportrange")
+ @ApiOperation(value = "get tcp and udp port range", code = HttpStatus.SC_OK,response = String.class, responseContainer = "List")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "port range not found", response = String.class),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get port range fail", response = String.class)})
+ @Produces(MediaType.APPLICATION_JSON)
+ @Timed
+ public String[] getTCP_UDP_portRange() {
+
+ return new String[]{ConfigUtil.getInstance().getTcpudpPortRangeStart(),ConfigUtil.getInstance().getTcpudpPortRangeEnd()};
+
+ }
+
+ @GET
+ @Path("/health")
+ @ApiOperation(value = "sdclient healthy check ", code = HttpStatus.SC_OK, response = String.class)
+ @ApiResponses(value = { @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "check fail", response = String.class) })
+ @Produces(MediaType.TEXT_PLAIN)
+ @Timed
+ public Response health() {
+
+ ArrayList<HealthCheck> healthcheckArray = new ArrayList<HealthCheck>();
+
+ // consul link check
+ healthcheckArray.add(new ConsulLinkHealthCheck());
+
+ // begin check
+ for (int i = 0; i < healthcheckArray.size(); i++) {
+ Result rst = healthcheckArray.get(i).execute();
+
+ if (!rst.isHealthy()) {
+ LOGGER.warn("health check failed:" + rst.getMessage());
+ throw new ExtendedInternalServerErrorException(rst.getMessage());
+ }
+ }
+
+ return Response.ok("sdclient healthy check:ok").build();
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java
new file mode 100644
index 0000000..65a808a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.core.AgentService;
+import org.onap.msb.sdclient.core.Node;
+import org.onap.msb.sdclient.wrapper.util.ConfigUtil;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.HttpClientUtil;
+import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ConsulAgentServiceWrapper {
+
+ private static ConsulAgentServiceWrapper instance = new ConsulAgentServiceWrapper();
+
+ private ConsulAgentServiceWrapper() {}
+
+ public static ConsulAgentServiceWrapper getInstance() {
+ return instance;
+ }
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulAgentServiceWrapper.class);
+
+
+ public synchronized int saveService(AgentService agentService) throws Exception{
+ String consulRegisterurl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_AGENT_URL).append("/register")).toString();
+
+
+ int registerResult =
+ HttpClientUtil.httpPostWithJSON(consulRegisterurl,
+ JacksonJsonUtil.beanToJson(agentService));
+
+ return registerResult;
+
+ }
+
+ public synchronized int deleteService(String serviceId) throws Exception{
+ String consulDelurl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_AGENT_URL).append("/deregister/").append(serviceId))
+ .toString();
+
+ int delResult = HttpClientUtil.httpPostWithJSON(consulDelurl, "");
+
+ return delResult;
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java
new file mode 100644
index 0000000..298dd54
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper;
+
+import org.onap.msb.sdclient.core.AgentService;
+import org.onap.msb.sdclient.core.CatalogNode;
+import org.onap.msb.sdclient.core.ConsulService;
+import org.onap.msb.sdclient.wrapper.util.ConfigUtil;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.HttpClientUtil;
+import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConsulCatalogServiceWrapper {
+
+ private static ConsulCatalogServiceWrapper instance = new ConsulCatalogServiceWrapper();
+
+ private ConsulCatalogServiceWrapper() {}
+
+ public static ConsulCatalogServiceWrapper getInstance() {
+ return instance;
+ }
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulAgentServiceWrapper.class);
+
+
+ public synchronized int saveService(AgentService agentService) throws Exception{
+ String consulRegisterurl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/register")).toString();
+
+ CatalogNode catalogNode=transformCatalogNode(agentService);
+
+
+ int registerResult =
+ HttpClientUtil.httpPostWithJSON(consulRegisterurl,
+ JacksonJsonUtil.beanToJson(catalogNode));
+
+ return registerResult;
+
+ }
+
+ public synchronized int deleteService(String serviceId) throws Exception{
+ String consulDelurl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/deregister"))
+ .toString();
+
+ String nodeJson="{\"Node\": \""+DiscoverUtil.EXTERNAL_NODE_NAME+"\",\"ServiceID\": \""+serviceId+"\"}";
+
+ int delResult = HttpClientUtil.httpPostWithJSON(consulDelurl, nodeJson);
+
+ return delResult;
+ }
+
+
+ private CatalogNode transformCatalogNode(AgentService agentService){
+ ConsulService consulService=new ConsulService();
+
+ consulService.setAddress(agentService.getAddress());
+ consulService.setId(agentService.getId());
+ consulService.setPort(agentService.getPort());
+ consulService.setService(agentService.getName());
+ consulService.setTags(agentService.getTags());
+
+ CatalogNode catalogNode=new CatalogNode(consulService);
+
+ return catalogNode;
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java
new file mode 100644
index 0000000..5f3fbc4
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java
@@ -0,0 +1,214 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.onap.msb.sdclient.core.KeyVaulePair;
+import org.onap.msb.sdclient.core.MicroServiceFullInfo;
+import org.onap.msb.sdclient.core.NodeInfo;
+import org.onap.msb.sdclient.wrapper.consul.Consul;
+import org.onap.msb.sdclient.wrapper.consul.HealthClient;
+import org.onap.msb.sdclient.wrapper.consul.cache.HealthCache;
+import org.onap.msb.sdclient.wrapper.consul.model.health.Service;
+import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConsulClientApp {
+
+ private final Consul consul;
+ private final HealthClient healthClient;
+// private AtomicReference<List<HealthCache>> cacheList = new AtomicReference<List<HealthCache>>(
+// new ArrayList<HealthCache>());
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulClientApp.class);
+
+ public ConsulClientApp(String ip, int port) {
+ URL url = null;
+ try {
+ url = new URL("http", ip, port, "");
+ } catch (MalformedURLException e1) {
+ // TODO Auto-generated catch block
+ LOGGER.error("start ConsulClientApp throw exception", e1);
+ throw new RuntimeException(e1);
+ }
+ this.consul = Consul.builder().withUrl(url).build(); // connect to Consul on localhost
+ this.healthClient = consul.healthClient();
+ }
+
+ public Consul getConsul() {
+ return consul;
+ }
+
+
+
+
+
+ /**
+ * @Title startHealthNodeListen
+ * @Description TODO(开启某个服务的node变化监听,只返回健康状态服务)
+ * @param serviceName
+ * @return
+ * @return HealthCache
+ */
+ public HealthCache startHealthNodeListen(final String serviceName) {
+ final HealthCache healthCache = HealthCache.newCache(healthClient, serviceName, 30);
+ healthCache.addListener(new HealthCache.Listener<String, ServiceHealth>() {
+ @Override
+ public void notify(Map<String, ServiceHealth> newValues) {
+ // do Something with updated server map
+ LOGGER.info(serviceName + "--new node notify--");
+
+
+ if (newValues.isEmpty()) {
+ LOGGER.warn(serviceName + "--nodeList is Empty--");
+ PublishAddressWrapper.publishApigateWayList.remove(serviceName);
+
+ try {
+ healthCache.stop();
+ LOGGER.info(serviceName + " Node Listen stopped");
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " Node Listen stop throw exception", e);
+ }
+
+ return;
+ }
+ //服务发现变化
+ List<MicroServiceFullInfo> nodeAddressList=new ArrayList<MicroServiceFullInfo>();
+ for (Map.Entry<String, ServiceHealth> entry : newValues.entrySet()) {
+
+ MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo();
+
+ ServiceHealth value = (ServiceHealth) entry.getValue();
+ Service service = value.getService();
+
+ NodeInfo node = new NodeInfo();
+ node.setIp(service.getAddress());
+ node.setPort(String.valueOf(service.getPort()));
+ Set<NodeInfo> nodes = new HashSet<NodeInfo>();
+ nodes.add(node);
+ microServiceInfo.setNodes(nodes);
+
+
+ microServiceInfo.setServiceName(serviceName);
+
+ try {
+ List<String> tagList = service.getTags();
+
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+
+ if (nsMap.get("namespace") != null) {
+ microServiceInfo.setNamespace(nsMap.get("namespace"));
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"labels\"")) {
+ String ms_labels_json = "{"+tag.split("\"labels\":\\{")[1];
+ Map<String, String> labelMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
+
+ List<String> nodeLabels = new ArrayList<String>();
+ for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) {
+ if ("visualRange".equals(labelEntry.getKey())) {
+ microServiceInfo.setVisualRange(labelEntry.getValue());
+ } else if ("network_plane_type".equals(labelEntry.getKey())) {
+ microServiceInfo.setNetwork_plane_type( labelEntry.getValue());
+ } else {
+ nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue());
+ }
+
+ }
+
+ microServiceInfo.setLabels(nodeLabels);
+ continue;
+ }
+
+ if (tag.startsWith("\"metadata\"")) {
+ String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1];
+ Map<String, String> metadataMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class);
+
+ List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>();
+
+
+ for (Map.Entry<String, String> metadataEntry : metadataMap.entrySet()) {
+ KeyVaulePair keyVaulePair = new KeyVaulePair();
+ keyVaulePair.setKey(metadataEntry.getKey());
+ keyVaulePair.setValue(metadataEntry.getValue());
+ ms_metadata.add(keyVaulePair);
+ }
+ microServiceInfo.setMetadata(ms_metadata);
+ continue;
+ }
+
+ }
+
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+ nodeAddressList.add(microServiceInfo);
+ }
+
+ PublishAddressWrapper.publishApigateWayList.put(serviceName, nodeAddressList);
+
+ }
+ });
+ try {
+ LOGGER.info(serviceName + " Node Listen start");
+// cacheList.get().add(healthCache);
+ healthCache.start();
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ LOGGER.error(serviceName + " Node Listen start throw exception", e);
+ }
+
+ return healthCache;
+ }
+
+
+
+ public static void main(String[] args) {
+ ConsulClientApp consulTest = new ConsulClientApp("127.0.0.1", 8500);
+ // 监听服务变化
+ consulTest.startHealthNodeListen("apigateway");
+
+
+ }
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java
new file mode 100644
index 0000000..48e783e
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java
@@ -0,0 +1,1946 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.core.AgentService;
+import org.onap.msb.sdclient.core.CatalogService;
+import org.onap.msb.sdclient.core.Check;
+import org.onap.msb.sdclient.core.ConsulResponse;
+import org.onap.msb.sdclient.core.HealthService;
+import org.onap.msb.sdclient.core.HealthService.Service;
+import org.onap.msb.sdclient.core.KeyVaulePair;
+import org.onap.msb.sdclient.core.MicroServiceFullInfo;
+import org.onap.msb.sdclient.core.MicroServiceInfo;
+import org.onap.msb.sdclient.core.Node;
+import org.onap.msb.sdclient.core.NodeAddress;
+import org.onap.msb.sdclient.core.NodeInfo;
+import org.onap.msb.sdclient.core.exception.ExtendedInternalServerErrorException;
+import org.onap.msb.sdclient.core.exception.ExtendedNotFoundException;
+import org.onap.msb.sdclient.core.exception.UnprocessableEntityException;
+import org.onap.msb.sdclient.wrapper.util.ConfigUtil;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.HttpClientUtil;
+import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil;
+import org.onap.msb.sdclient.wrapper.util.RegExpTestUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+public class ConsulServiceWrapper {
+
+
+ private static ConsulServiceWrapper instance = new ConsulServiceWrapper();
+
+
+ private ConsulServiceWrapper() {}
+
+ public static ConsulServiceWrapper getInstance() {
+ return instance;
+ }
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulServiceWrapper.class);
+
+ /**
+ * Title: getAllMicroServiceInstances Description: 获取全部服务
+ *
+ * @return
+ * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#getAllMicroServiceInstances()
+ */
+ public List<MicroServiceFullInfo> getAllMicroServiceInstances() {
+
+ String consulServiceUrl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/services")).toString();
+
+ String resultJson = HttpClientUtil.httpGet(consulServiceUrl);
+ Map<String, String[]> catalogServiceMap =
+ (Map<String, String[]>) JacksonJsonUtil.jsonToMapBean(resultJson);
+
+ List<MicroServiceFullInfo> microServiceFullInfoArray = new ArrayList<MicroServiceFullInfo>();
+
+ if(catalogServiceMap.isEmpty()){
+ return microServiceFullInfoArray;
+ }
+
+ for (Map.Entry<String, String[]> entry : catalogServiceMap.entrySet()) {
+ Set<String> versionSet = new HashSet<String>();
+
+ Set<String> nsSet = new HashSet<String>();
+ nsSet.add("");
+
+ String consul_serviceName = entry.getKey().toString();
+ String[] tagList = entry.getValue();
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+ try {
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("version") != null) {
+ versionSet.add( baseMap.get("version"));
+ }
+ else{
+ versionSet.add("");
+ }
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage());
+ }
+
+ continue;
+
+ }
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+
+ try {
+ Map<String, String> namespaceMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+ if (namespaceMap.get("namespace") != null) {
+ nsSet.add(namespaceMap.get("namespace"));
+ } else {
+ nsSet.add("");
+ }
+
+ continue;
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ LOGGER.error(e.getMessage());
+ }
+
+ continue;
+
+ }
+
+
+ }
+
+ for(String ms_version:versionSet){
+ for (String ns : nsSet) {
+ MicroServiceFullInfo microServiceFullInfo =
+ getMicroServiceInstanceForAll(consul_serviceName, ms_version, ns);
+ if (microServiceFullInfo != null && !"consul".equals(microServiceFullInfo.getServiceName())) {
+
+ microServiceFullInfoArray.add(microServiceFullInfo);
+ }
+ }
+ }
+
+
+ }
+
+
+ return microServiceFullInfoArray;
+ }
+
+
+
+
+ /**
+ * @Title getMicroServiceInstanceForAll
+ * @Description TODO(通过列表遍历获取单个服务信息)
+ * @param consul_serviceName
+ * @param version
+ * @param namespace
+ * @return
+ * @return MicroServiceFullInfo
+ */
+ public MicroServiceFullInfo getMicroServiceInstanceForAll(String consul_serviceName, String version,
+ String namespace) {
+
+ try{
+ ConsulResponse consulResponse = getHealthServices(consul_serviceName, false, "", "");
+ if (consulResponse == null) {
+ LOGGER.error( "microservice not found: serviceName-" + consul_serviceName+", namespace-"+namespace);
+ return null;
+ }
+
+ String serviceName=consul_serviceName;
+ if (StringUtils.isNotBlank(namespace)) {
+ if(consul_serviceName.endsWith("-"+namespace)){
+ serviceName=consul_serviceName.substring(0,consul_serviceName.length()-namespace.length()-1);
+ }
+ }
+
+
+ ConsulResponse serviceResponse =
+ getMicroServiceInfo(consulResponse,serviceName,version,
+ false, "",namespace);
+ return (MicroServiceFullInfo) serviceResponse.getResponse();
+ }
+ catch(Exception e){
+ if(StringUtils.isNotBlank(namespace)){
+ LOGGER.error("get service List have error:serviceName["+consul_serviceName+"],version["+version+"],namespace["+namespace+"]:"+e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * @Title getMicroServiceInstance
+ * @Description TODO(通过Rest接口获取单个服务信息)
+ * @param serviceName
+ * @param version
+ * @param ifPassStatus
+ * @param wait
+ * @param index
+ * @param labels
+ * @param namespace
+ * @return
+ * @return ConsulResponse
+ */
+ public ConsulResponse getMicroServiceInstance(String serviceName, String version,
+ boolean ifPassStatus, String wait, String index, String labels, String namespace){
+
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+
+ checkServiceNameAndVersion(serviceName,version);
+
+ if (!RegExpTestUtil.labelRegExpTest(labels)) {
+ throw new UnprocessableEntityException(
+ "get MicroServiceInfo FAIL: The label query parameter format is wrong (key:value)");
+ }
+
+ String consul_serviceName=getServiceName4Consul(serviceName,namespace);
+
+ ConsulResponse consulResponse = getHealthServices(consul_serviceName, ifPassStatus, wait, index);
+ if (consulResponse == null) {
+ String errInfo = "microservice not found: serviceName-" + serviceName+", namespace-"+namespace;
+ throw new ExtendedNotFoundException(errInfo);
+ }
+
+ return getMicroServiceInfo(consulResponse,serviceName,version,
+ ifPassStatus, labels,namespace);
+
+ }
+
+
+
+ /**
+ * Title: getMicroServiceInstance Description:获取指定服务信息
+ *
+ * @param serviceName
+ * @param version
+ * @return
+ * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#getMicroServiceInstance(java.lang.String,
+ * java.lang.String)
+ */
+
+ public ConsulResponse getMicroServiceInfo(ConsulResponse consulResponse,String serviceName, String version,
+ boolean ifPassStatus, String labels, String namespace) {
+ // TODO Auto-generated method stub
+
+
+
+ String resultJson = (String) consulResponse.getResponse();
+ List<HealthService> healthServiceList =
+ JacksonJsonUtil.jsonToListBean(resultJson, new TypeReference<List<HealthService>>() {});
+
+
+ if (healthServiceList == null || healthServiceList.size() == 0) {
+ String errInfo = "microservice not found: serviceName-" + serviceName+", namespace-"+namespace;
+ throw new ExtendedNotFoundException(errInfo);
+
+ }
+
+ try {
+
+ // label query,format key:value|value2,key2:value2
+ boolean islabelQuery = false;
+ Map<String, String> query_labelMap = new HashMap<String, String>();
+ if (StringUtils.isNotBlank(labels)) {
+ islabelQuery = true;
+ String[] routeLabels = StringUtils.split(labels, ",");
+
+ for (int i = 0; i < routeLabels.length; i++) {
+ String[] labelArray = StringUtils.split(routeLabels[i], ":");
+ query_labelMap.put(labelArray[0], labelArray[1]);
+ }
+ }
+
+
+ MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo();
+ Set<NodeInfo> nodes = new HashSet<NodeInfo>();
+ Set<String> serviceLabels = new HashSet<String>();
+ Set<KeyVaulePair> serviceMetadatas = new HashSet<KeyVaulePair>();
+ Set<String> serviceNetworkPlane = new HashSet<String>();
+ String nodeNamespace = "";
+
+
+
+ for (HealthService healthService : healthServiceList) {
+ Service service = healthService.getService();
+ List<String> tagList = service.getTags();
+
+ String ms_url = "", ms_version = "", ms_protocol = "", ms_status = "", ms_publish_port = "", ms_is_manual =
+ "", ms_visualRange = "1", ms_network_plane_type = "",ms_lb_policy="",ms_host="",ms_path="";
+ List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>();
+
+ List<String> nodeLabels = new ArrayList<String>();
+ Map<String, String> labelMap = new HashMap<String, String>();
+
+ NodeInfo node = new NodeInfo();
+
+ node.setIp(service.getAddress());
+ node.setPort(String.valueOf(service.getPort()));
+ node.setNodeId(service.getId());
+
+
+
+ try {
+
+ for (String tag : tagList) {
+
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ ms_url = (baseMap.get("url") == null ? "" : baseMap.get("url"));
+ ms_version = (baseMap.get("version") == null ? "" : baseMap.get("version"));
+ ms_protocol = (baseMap.get("protocol") == null ? "" : baseMap.get("protocol"));
+ ms_status = (baseMap.get("status") == null ? "1" : baseMap.get("status"));
+
+ if (baseMap.get("publish_port") != null) {
+ ms_publish_port = (baseMap.get("publish_port"));
+ }
+
+ if (baseMap.get("is_manual") != null) {
+ ms_is_manual = baseMap.get("is_manual");
+
+ }
+
+ if (baseMap.get("ha_role") != null) {
+ node.setHa_role(baseMap.get("ha_role"));
+ }
+
+ if (baseMap.get("host") != null) {
+ ms_host=baseMap.get("host");
+ }
+
+ if (baseMap.get("path") != null) {
+ ms_path=baseMap.get("path");
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"labels\"")) {
+ String ms_labels_json = "{"+tag.split("\"labels\":\\{")[1];
+ labelMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
+
+
+
+ for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) {
+ if ("visualRange".equals(labelEntry.getKey())) {
+ ms_visualRange = labelEntry.getValue();
+ } else if ("network_plane_type".equals(labelEntry.getKey())) {
+ ms_network_plane_type = labelEntry.getValue();
+ } else {
+ nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue());
+ }
+
+ }
+
+
+ continue;
+ }
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_namespace_json = tag.split("\"ns\":")[1];
+ Map<String, String> namespaceMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_namespace_json, Map.class);
+
+ if (namespaceMap.get("namespace") != null) {
+ nodeNamespace = namespaceMap.get("namespace");
+ } else {
+ nodeNamespace = "";
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"lb\"")) {
+ String ms_lb_json = tag.split("\"lb\":")[1];
+ Map<String, String> lbMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_lb_json, Map.class);
+
+ if (lbMap.get("lb_policy") != null) {
+ ms_lb_policy = lbMap.get("lb_policy");
+ if (ms_lb_policy.startsWith("hash") || ms_lb_policy.equals("ip_hash")) {
+ ms_lb_policy = "ip_hash";
+ }
+
+ }
+
+ if (lbMap.get("lb_server_params") != null) {
+ node.setLb_server_params(lbMap.get("lb_server_params").replace(" ", ","));
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"checks\"")) {
+ String ms_check_json = tag.split("\"checks\":")[1];
+ Map<String, String> checkMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class);
+
+
+ //自动注册健康检查
+ if (StringUtils.isNotBlank(checkMap.get("ttl"))){
+ node.setCheckType("TTL");
+ node.setTtl(checkMap.get("ttl"));
+ }
+ else if(StringUtils.isNotBlank(checkMap.get("http"))){
+ node.setCheckType("HTTP");
+ node.setCheckUrl(checkMap.get("http"));
+ if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval"));
+ if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout"));
+ }
+ else if(StringUtils.isNotBlank(checkMap.get("tcp"))){
+ node.setCheckType("TCP");
+ node.setCheckUrl(checkMap.get("tcp"));
+ if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval"));
+ if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout"));
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"metadata\"")) {
+ String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1];
+ Map<String, String> metadataMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class);
+
+
+
+ for (Map.Entry<String, String> entry : metadataMap.entrySet()) {
+ KeyVaulePair keyVaulePair = new KeyVaulePair();
+ keyVaulePair.setKey(entry.getKey());
+ keyVaulePair.setValue(entry.getValue());
+ ms_metadata.add(keyVaulePair);
+ }
+
+ continue;
+ }
+
+
+
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+ // 健康检查信息
+ List<Check> checks = healthService.getChecks();
+ node.setStatus("passing");
+ for (Check check : checks) {
+ if (!"passing".equals(check.getStatus())) {
+ node.setStatus(check.getStatus());
+ break;
+ }
+ }
+
+ if (!ms_version.equals(version)) {
+ continue;
+ }
+
+ // namespace过滤
+ if (!namespace.equals(nodeNamespace)) {
+ continue;
+ }
+
+ // 标签过滤
+ if (islabelQuery) {
+ boolean ifMatchLabel = false;
+ for (Map.Entry<String, String> query_entry : query_labelMap.entrySet()) {
+ String key = query_entry.getKey();
+ String value = query_entry.getValue();
+ if (StringUtils.isBlank(labelMap.get(key))) {
+ continue;
+ }
+
+ String[] queryTagArray = StringUtils.split(value, "|");
+ String[] serviceTagArray = StringUtils.split(labelMap.get(key), "|");
+ if (DiscoverUtil.contain(queryTagArray, serviceTagArray)) {
+ ifMatchLabel = true;
+ break;
+ }
+
+ }
+
+ if (!ifMatchLabel) {
+ continue;
+ }
+ }
+
+
+ nodes.add(node);
+ serviceLabels.addAll(nodeLabels);
+ serviceMetadatas.addAll(ms_metadata);
+
+ String[] network_plane_array=StringUtils.split(ms_network_plane_type, "|");
+ for(int i=0;i<network_plane_array.length;i++){
+ serviceNetworkPlane.add(network_plane_array[i]);
+ }
+
+
+
+ microServiceInfo.setServiceName(serviceName);
+ microServiceInfo.setUrl(ms_url);
+ microServiceInfo.setVersion(ms_version);
+ microServiceInfo.setProtocol(ms_protocol);
+ microServiceInfo.setStatus(ms_status);
+ microServiceInfo.setPublish_port(ms_publish_port);
+ microServiceInfo.setIs_manual(Boolean.parseBoolean(ms_is_manual));
+ microServiceInfo.setVisualRange(ms_visualRange);
+
+ microServiceInfo.setLb_policy(ms_lb_policy);
+ microServiceInfo.setNamespace(namespace);
+ microServiceInfo.setHost(ms_host);
+ microServiceInfo.setPath(ms_path);
+ }
+
+
+ if (nodes.isEmpty()) {
+
+
+ String errInfo =
+ "microservice not found: serviceName-" + serviceName + ",version-" + version
+ + ",namespace-" + namespace + ",labels-" + labels;
+ throw new ExtendedNotFoundException(errInfo);
+
+ }
+
+
+
+ microServiceInfo.setLabels(new ArrayList<String>(serviceLabels));
+ microServiceInfo.setMetadata(new ArrayList<KeyVaulePair>(serviceMetadatas));
+ microServiceInfo.setNodes(nodes);
+ microServiceInfo.setNetwork_plane_type(StringUtils.join(serviceNetworkPlane.toArray(), "|"));
+
+
+
+ return new ConsulResponse(microServiceInfo, consulResponse.getIndex());
+
+
+ } catch (ExtendedNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ExtendedInternalServerErrorException(e.getMessage());
+ }
+
+
+ }
+
+
+
+ public MicroServiceFullInfo updateMicroServiceInstance(String serviceName, String version,
+ String namespace, MicroServiceInfo microServiceInfo, String requestIP,boolean is_manual) {
+ //数据格式效验
+ checkMicroServiceInfo(microServiceInfo);
+ deleteMicroService(serviceName, version,namespace);
+ return saveMicroServiceInstance(microServiceInfo, true, requestIP,is_manual);
+ }
+
+ /**
+ * Title: saveMicroServiceInstance Description: 保存服务信息
+ *
+ * @param microServiceInfo
+ * @param createOrUpdate true:添加或追加更新 false:覆盖
+ * @param requestIP 访问请求IP地址
+ * @return
+ * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#saveMicroServiceInstance(org.onap.msb.sdclient.core.MicroServiceInfo,
+ * boolean, java.lang.String)
+ */
+ public MicroServiceFullInfo saveMicroServiceInstance(MicroServiceInfo microServiceInfo,
+ boolean createOrUpdate, String requestIP,boolean is_manual) {
+
+ //数据格式效验
+ checkMicroServiceInfo(microServiceInfo);
+
+ String serviceName = microServiceInfo.getServiceName().trim();
+
+ if (createOrUpdate == false) {
+ // 覆盖原记录,先删除后添加
+ try{
+ deleteMicroService(microServiceInfo.getServiceName(), microServiceInfo.getVersion(),
+ microServiceInfo.getNamespace());
+ }
+ catch (ExtendedNotFoundException e) {
+ String errInfo = "microservice not found: serviceName-" + microServiceInfo.getServiceName() + ",version-" + microServiceInfo.getVersion()+ " ,namespace-" + microServiceInfo.getNamespace();
+ LOGGER.warn(errInfo);
+ }
+
+
+
+ }
+
+ Set<Node> nodes = microServiceInfo.getNodes();
+ String[] visualRangeArray = StringUtils.split(microServiceInfo.getVisualRange(), "|");
+
+ try {
+
+ for (Node node : nodes) {
+ AgentService agentService = new AgentService();
+
+ if (StringUtils.isBlank(node.getIp())) {
+ node.setIp(requestIP);
+ }
+
+ String serverId =
+ microServiceInfo.getNamespace() + "_" + serviceName + "_" + node.getIp() + "_"
+ + node.getPort();
+
+
+ List<String> tags = new ArrayList<String>();
+
+ Map<String, String> baseMap = new HashMap<String, String>();
+ Map<String, String> lbMap = new HashMap<String, String>();
+ Map<String, String> labelMap = new HashMap<String, String>();
+ Map<String, String> metadataMap = new HashMap<String, String>();
+ Map<String, String> checkMap = new HashMap<String, String>();
+ Map<String, String> nsMap = new HashMap<String, String>();
+ //Map<String, String> nodeMap = new HashMap<String, String>();
+
+ baseMap.put("url", microServiceInfo.getUrl());
+ baseMap.put("protocol", microServiceInfo.getProtocol());
+ baseMap.put("version", microServiceInfo.getVersion());
+
+ baseMap.put("status", "1");
+ baseMap.put("is_manual", Boolean.toString(is_manual));
+
+ // TCP和UDP协议保存 nginx端口和负载均衡策略
+ if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) {
+ baseMap.put("publish_port", microServiceInfo.getPublish_port());
+ }
+ String lb_policy = microServiceInfo.getLb_policy();
+
+ // 保存服务的负载均衡策略
+ if (StringUtils.isNotBlank(lb_policy)) {
+ switch (lb_policy) {
+ case "round-robin":
+ break;
+ case "ip_hash":
+ if ("TCP".equals(microServiceInfo.getProtocol())
+ || "UDP".equals(microServiceInfo.getProtocol())) {
+ lbMap.put("lb_policy", "hash $remote_addr");
+ } else {
+ lbMap.put("lb_policy", "ip_hash");
+ }
+ break;
+ default:
+ lbMap.put("lb_policy", lb_policy);
+ break;
+ }
+
+ }
+
+ if (StringUtils.isNotBlank(node.getLb_server_params())) {
+ lbMap.put("lb_server_params", node.getLb_server_params().trim().replace(",", " "));
+
+ }
+
+ if (StringUtils.isNotBlank(node.getHa_role())) {
+ baseMap.put("ha_role", node.getHa_role());
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getHost())) {
+ baseMap.put("host", microServiceInfo.getHost().toLowerCase());
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getPath())) {
+ baseMap.put("path",microServiceInfo.getPath());
+ }
+
+ // 保存健康检查参数
+ if (StringUtils.isNotBlank(node.getCheckType())) {
+
+ AgentService.Check check = agentService.createCheck();
+
+ if ("TTL".equals(node.getCheckType())) {
+ check.setTtl(node.getTtl());
+ checkMap.put("ttl", node.getTtl());
+
+ } else if ("HTTP".equals(node.getCheckType())) {
+ check.setInterval(node.getCheckInterval());
+ check.setHttp(node.getCheckUrl());
+ check.setTimeout(node.getCheckTimeOut());
+
+ checkMap.put("http", node.getCheckUrl());
+ checkMap.put("interval",node.getCheckInterval());
+ checkMap.put("timeout", node.getCheckTimeOut());
+ } else if ("TCP".equals(node.getCheckType())) {
+ check.setInterval(node.getCheckInterval());
+ check.setTcp(node.getCheckUrl());
+ check.setTimeout(node.getCheckTimeOut());
+
+ checkMap.put("tcp", node.getCheckUrl());
+ checkMap.put("interval", node.getCheckInterval());
+ checkMap.put("timeout",node.getCheckTimeOut());
+ }
+
+ agentService.setCheck(check);
+ }
+
+
+ List<KeyVaulePair> keyVaulePairs = microServiceInfo.getMetadata();
+
+ if (keyVaulePairs != null && keyVaulePairs.size() > 0) {
+ for (KeyVaulePair keyVaulePair : keyVaulePairs) {
+ metadataMap.put(keyVaulePair.getKey(), keyVaulePair.getValue());
+ }
+ }
+
+ // 同步过滤参数组合为json格式存储
+ labelMap.put("visualRange", StringUtils.join(visualRangeArray, "|"));
+
+ if (StringUtils.isNotBlank(microServiceInfo.getNetwork_plane_type())) {
+ labelMap.put("network_plane_type", microServiceInfo.getNetwork_plane_type());
+ }
+ if(microServiceInfo.getLabels()!=null){
+ for (String label : microServiceInfo.getLabels()) {
+ String[] labelArray = StringUtils.split(label, ":");
+ if(labelArray.length==2){
+ labelMap.put(labelArray[0], labelArray[1]);
+ }
+ }
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getNamespace())) {
+ nsMap.put("namespace", microServiceInfo.getNamespace());
+ }
+
+
+
+ tags.add("\"base\":" + JacksonJsonUtil.beanToJson(baseMap));
+ if(!lbMap.isEmpty()) tags.add("\"lb\":" + JacksonJsonUtil.beanToJson(lbMap));
+ if(!checkMap.isEmpty()) tags.add("\"checks\":" + JacksonJsonUtil.beanToJson(checkMap));
+ if(!labelMap.isEmpty()) tags.add("\"labels\":" + JacksonJsonUtil.beanToJson(labelMap));
+ if(!metadataMap.isEmpty()) tags.add("\"metadata\":" + JacksonJsonUtil.beanToJson(metadataMap));
+ if(!nsMap.isEmpty()) tags.add("\"ns\":" + JacksonJsonUtil.beanToJson(nsMap));
+
+ agentService.setTags(tags);
+
+ agentService.setAddress(node.getIp());
+ agentService.setId(serverId);
+ agentService.setPort(Integer.parseInt(node.getPort()));
+
+ String consul_serviceName=getServiceName4Consul(serviceName,microServiceInfo.getNamespace());
+
+
+ agentService.setName(consul_serviceName);
+
+ int registerResult;
+ if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){
+ registerResult =ConsulCatalogServiceWrapper.getInstance().saveService(agentService);
+ }
+ else{
+ registerResult =ConsulAgentServiceWrapper.getInstance().saveService(agentService);
+ }
+
+ if (registerResult != 200) {
+ throw new Exception("register consul service fail:" + registerResult);
+ }
+
+
+
+ }
+
+ LOGGER.info( "save microservice success: serviceName-" + microServiceInfo.getServiceName() + ",version-" + microServiceInfo.getVersion()+ " ,namespace-" + microServiceInfo.getNamespace());
+
+ return getMicroServiceInstance(serviceName, microServiceInfo.getVersion(),
+ microServiceInfo.getNamespace());
+
+
+ } catch (ExtendedNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ LOGGER.error("register consul service throw exception", e);
+ throw new ExtendedInternalServerErrorException(e.getMessage());
+
+ }
+
+
+
+ }
+
+ public MicroServiceFullInfo getMicroServiceInstance(String serviceName, String version,
+ String namespace) {
+ ConsulResponse serviceResponse =
+ getMicroServiceInstance(serviceName, version, false, "", "", "", namespace);
+ return (MicroServiceFullInfo) serviceResponse.getResponse();
+ }
+
+
+ /**
+ * Title: deleteMicroService Description: 删除服务信息
+ *
+ * @param serviceName
+ * @param version
+ * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#deleteMicroService(java.lang.String,
+ * java.lang.String)
+ */
+ public void deleteMicroService(String serviceName, String version, String namespace) {
+
+
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+ checkServiceNameAndVersion(serviceName,version);
+
+
+ String consul_serviceName=getServiceName4Consul(serviceName,namespace);
+
+ List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version);
+
+
+ if (catalogServiceList == null || catalogServiceList.size() == 0) {
+ String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version+ " ,namespace-" + namespace;
+ throw new ExtendedNotFoundException(errInfo);
+
+ }
+
+ boolean ifFindServiceForNS = false;
+
+ for (CatalogService catalogService : catalogServiceList) {
+
+ List<String> tagList = catalogService.getServiceTags();
+ String serviceNamespace = "",serviceVersion="";
+ try {
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+
+
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+ if (nsMap.get("namespace") != null) {
+ serviceNamespace = nsMap.get("namespace");
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("version") != null) {
+ serviceVersion= baseMap.get("version");
+ }
+
+
+ continue;
+
+ }
+
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+ if (!serviceNamespace.equals(namespace)) {
+ continue;
+ }
+
+ if(!serviceVersion.equals(version)){
+ continue;
+ }
+ ifFindServiceForNS = true;
+ String serviceID = catalogService.getServiceId();
+ try {
+
+ int delResult;
+ if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){
+ delResult =ConsulCatalogServiceWrapper.getInstance().deleteService(serviceID);
+ }
+ else{
+ delResult =ConsulAgentServiceWrapper.getInstance().deleteService(serviceID);
+ }
+
+ if (delResult != 200) {
+ throw new Exception("delete consul service fail:" + delResult);
+ }
+
+
+ } catch (Exception e) {
+ LOGGER.error("delete consul service throw exception", e);
+ throw new ExtendedInternalServerErrorException(e.getMessage());
+
+ }
+
+ }
+
+
+ if (!ifFindServiceForNS) {
+ String errInfo =
+ "microservice not found: serviceName-" + serviceName + ",version-" + version
+ + ",namespace-" + namespace;
+ throw new ExtendedNotFoundException(errInfo);
+ }
+
+ LOGGER.info("microservice delete success: serviceName-" + serviceName + ",version-" + version
+ + ",namespace-" + namespace);
+
+ }
+
+ /**
+ * Title: deleteMicroServiceInstance Description: 刪除服务的节点信息
+ *
+ * @param serviceName
+ * @param version
+ * @param ip
+ * @param port
+ * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#deleteMicroServiceInstance(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void deleteMicroServiceInstance(String serviceName, String version, String namespace,
+ String ip, String port) {
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+ checkServiceNameAndVersion(serviceName,version);
+
+
+ if (!RegExpTestUtil.ipRegExpTest(ip)) {
+ throw new UnprocessableEntityException("delete MicroServiceInfo FAIL:IP(" + ip
+ + ")is not a valid IP address");
+ }
+
+ if (!RegExpTestUtil.portRegExpTest(port)) {
+ throw new UnprocessableEntityException("delete MicroServiceInfo FAIL:Port(" + port
+ + ")is not a valid Port address");
+ }
+
+ String consul_serviceName=getServiceName4Consul(serviceName,namespace);
+
+ List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version);
+
+
+ if (catalogServiceList == null || catalogServiceList.size() == 0) {
+ String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version;
+ LOGGER.warn(errInfo);
+ throw new ExtendedNotFoundException(errInfo);
+
+ }
+
+ String node = "", serviceID = "";
+ boolean ifFindBNode = false;
+
+
+ for (CatalogService catalogService : catalogServiceList) {
+
+ String serviceAddress = catalogService.getServiceAddress();
+ String servicePort = String.valueOf(catalogService.getServicePort());
+
+
+
+ List<String> tagList = catalogService.getServiceTags();
+ String ms_version = "", ms_namespace = "";
+ try {
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("version") != null) {
+ ms_version = baseMap.get("version");
+ }
+
+
+ }
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+
+
+
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+ if (nsMap.get("namespace") != null) {
+ ms_namespace = nsMap.get("namespace");
+ }
+
+
+ }
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+ if (serviceAddress.equals(ip) && servicePort.equals(port) && ms_version.equals(version)
+ && ms_namespace.equals(namespace)) {
+ node = catalogService.getNode();
+ serviceID = catalogService.getServiceId();
+ ifFindBNode = true;
+ break;
+ }
+
+
+ }
+
+ if (!ifFindBNode) {
+ throw new ExtendedNotFoundException("delete MicroServiceInfo FAIL: node-" + ip + ":" + port
+ + " namespace-" + namespace + " not found ");
+ }
+
+
+
+ try {
+ int delResult;
+ if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){
+ delResult =ConsulCatalogServiceWrapper.getInstance().deleteService(serviceID);
+ }
+ else{
+ delResult =ConsulAgentServiceWrapper.getInstance().deleteService(serviceID);
+ }
+
+ if (delResult != 200) {
+ throw new Exception("delete consul service fail:" + delResult);
+ }
+
+
+ } catch (Exception e) {
+ LOGGER.error("delete consul service throw exception", e);
+ throw new ExtendedInternalServerErrorException(e.getMessage());
+
+ }
+
+ }
+
+ /**
+ * @Title getConsulServices
+ * @Description TODO(通过方法:根据服务名\版本号获取consul服务信息)
+ * @param serviceName
+ * @return
+ * @return List<CatalogService>
+ */
+ private List<CatalogService> getConsulServices(String serviceName, String version) {
+ // serviceName = serviceName.replace("/", "*");
+ String consulServiceUrl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/service/").append(serviceName))
+ .toString();
+
+ String resultJson = HttpClientUtil.httpGet(consulServiceUrl);
+ List<CatalogService> catalogServiceList =
+ (List<CatalogService>) JacksonJsonUtil.jsonToListBean(resultJson);
+
+ for (CatalogService catalogService : catalogServiceList) {
+
+
+ List<String> tagList = catalogService.getServiceTags();
+ String ms_version = "";
+ try {
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("version") != null) {
+ ms_version = baseMap.get("version");
+ }
+
+ break;
+
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+ if (!ms_version.equals(version)) {
+ catalogServiceList.remove(catalogService);
+ break;
+ }
+
+
+ }
+ return catalogServiceList;
+ }
+
+ /**
+ * @Title getHealthServices
+ * @Description TODO(通过方法:根据服务名获取consul服务健康检查信息)
+ * @param serviceName
+ * @return List<HealthService>
+ */
+ private ConsulResponse getHealthServices(String serviceName, boolean ifPassStatus, String wait,
+ String index) {
+ // serviceName = serviceName.replace("/", "*");
+ StringBuilder healthServiceUrlBuilder =
+ new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_HEALTH_URL).append(serviceName);
+
+ if (ifPassStatus) {
+ healthServiceUrlBuilder.append("?passing");
+ }
+
+ if (StringUtils.isNotBlank(wait) && StringUtils.isNotBlank(index)) {
+ if (ifPassStatus) {
+ healthServiceUrlBuilder.append("&wait=").append(wait).append("&index=").append(index);
+ } else {
+ healthServiceUrlBuilder.append("?wait=").append(wait).append("&index=").append(index);
+ }
+ }
+
+ return HttpClientUtil.httpWaitGet(healthServiceUrlBuilder.toString());
+
+ }
+
+
+
+ public void healthCheckbyTTL(String serviceName, String version, String namespace,
+ NodeAddress checkNode) {
+ // TODO Auto-generated method stub
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+ checkServiceNameAndVersion(serviceName,version);
+
+
+ if (!RegExpTestUtil.ipRegExpTest(checkNode.getIp())) {
+ throw new UnprocessableEntityException("healthCheck by TTL FAIL:IP(" + checkNode.getIp()
+ + ")is not a valid IP address");
+ }
+
+ if (!RegExpTestUtil.portRegExpTest(checkNode.getPort())) {
+ throw new UnprocessableEntityException("healthCheck by TTL FAIL:Port(" + checkNode.getPort()
+ + ")is not a valid Port address");
+ }
+
+ String consul_serviceName=getServiceName4Consul(serviceName,namespace);
+
+ List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version);
+
+
+ if (catalogServiceList == null || catalogServiceList.size() == 0) {
+ String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version;
+ LOGGER.warn(errInfo);
+ throw new ExtendedNotFoundException(errInfo);
+
+ }
+
+
+ boolean ifFindBNode = false;
+
+
+ for (CatalogService catalogService : catalogServiceList) {
+
+ String serviceAddress = catalogService.getServiceAddress();
+ String servicePort = String.valueOf(catalogService.getServicePort());
+ boolean ifttlCheck = false;
+
+
+ List<String> tagList = catalogService.getServiceTags();
+ String ms_version = "", ms_namespace = "";
+ try {
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("version") != null) {
+ ms_version = baseMap.get("version");
+ }
+ }
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+ if (nsMap.get("namespace") != null) {
+ ms_namespace = nsMap.get("namespace");
+ }
+ }
+
+
+ if (tag.startsWith("\"checks\"")) {
+ String ms_check_json = tag.split("\"checks\":")[1];
+ Map<String, String> checkMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class);
+
+ //自动注册健康检查
+ if (StringUtils.isNotBlank(checkMap.get("ttl"))){
+ ifttlCheck=true;
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+
+
+
+ if (serviceAddress.equals(checkNode.getIp()) && servicePort.equals(checkNode.getPort()) && ms_version.equals(version)
+ && ms_namespace.equals(namespace)) {
+ if(!ifttlCheck){
+ throw new ExtendedNotFoundException("healthCheck by TTL FAIL: Service is not enabled TTL health check ");
+ }
+ ifFindBNode = true;
+ break;
+ }
+
+
+ }
+
+
+
+ if (!ifFindBNode) {
+ throw new ExtendedNotFoundException("healthCheck by TTL FAIL: node-" + checkNode.getIp() + ":" + checkNode.getPort()
+ + " namespace-" + namespace + " not found ");
+ }
+
+
+
+
+
+ try {
+ String checkID =
+ (new StringBuilder().append("service:").append(namespace).append("_").append(serviceName)
+ .append("_").append(checkNode.getIp()).append("_").append(checkNode.getPort()))
+ .toString();
+
+ String consulServiceUrl =
+ (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress())
+ .append(DiscoverUtil.CONSUL_AGENT_TTL_URL).append(checkID)).toString();
+
+ String result= HttpClientUtil.httpGet(consulServiceUrl);
+ if("CheckID does not have associated TTL".equals(result)){
+ throw new ExtendedNotFoundException("healthCheck by TTL FAIL: Service is not enabled TTL health check ");
+ }
+
+ }
+ catch (ExtendedInternalServerErrorException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new ExtendedInternalServerErrorException("healthCheck by TTL FAIL:" + e.getMessage());
+ }
+
+
+
+ }
+
+// public MicroServiceFullInfo getApigatewayServiceInfo4Host(String namespace){
+// return getMicroServiceInstance(DiscoverUtil.APIGATEWAY_SERVINCE, "v1", namespace);
+// }
+//
+
+
+
+
+
+ public List<MicroServiceFullInfo> getMicroServiceForNodes(String serviceName, String version, boolean ifPassStatus,String labels,String namespace){
+ // TODO Auto-generated method stub
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+ checkServiceNameAndVersion(serviceName,version);
+
+ if (!RegExpTestUtil.labelRegExpTest(labels)) {
+ throw new UnprocessableEntityException(
+ "get MicroServiceInfo FAIL: The label query parameter format is wrong (key:value)");
+ }
+
+
+ String consul_serviceName=getServiceName4Consul(serviceName,namespace);
+
+ ConsulResponse consulResponse = getHealthServices(consul_serviceName, ifPassStatus, "", "");
+ if (consulResponse == null) {
+ String errInfo = "microservice not found: serviceName-" + serviceName;
+ throw new ExtendedNotFoundException(errInfo);
+ }
+ String resultJson = (String) consulResponse.getResponse();
+ List<HealthService> healthServiceList =
+ JacksonJsonUtil.jsonToListBean(resultJson, new TypeReference<List<HealthService>>() {});
+
+
+ if (healthServiceList == null || healthServiceList.size() == 0) {
+ String errInfo = "microservice not found: serviceName-" + serviceName;
+ throw new ExtendedNotFoundException(errInfo);
+ }
+
+ try {
+
+ // label query,format key:value|value2,key2:value2
+ boolean islabelQuery = false;
+ Map<String, String> query_labelMap = new HashMap<String, String>();
+ if (StringUtils.isNotBlank(labels)) {
+ islabelQuery = true;
+ String[] routeLabels = StringUtils.split(labels, ",");
+
+ for (int i = 0; i < routeLabels.length; i++) {
+ String[] labelArray = StringUtils.split(routeLabels[i], ":");
+ query_labelMap.put(labelArray[0], labelArray[1]);
+ }
+ }
+
+ List<MicroServiceFullInfo> microServiceInfoList=new ArrayList<MicroServiceFullInfo>();
+
+
+
+ for (HealthService healthService : healthServiceList) {
+
+ Set<NodeInfo> nodes = new HashSet<NodeInfo>();
+ Set<String> serviceLabels = new HashSet<String>();
+ String nodeNamespace = "";
+ MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo();
+
+ Service service = healthService.getService();
+ List<String> tagList = service.getTags();
+
+ String ms_url = "", ms_version = "", ms_protocol = "", ms_status = "", ms_publish_port = "", ms_is_manual =
+ "", ms_visualRange = "1", ms_network_plane_type = "",ms_lb_policy="",ms_host="",ms_path="";
+ List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>();
+
+ List<String> nodeLabels = new ArrayList<String>();
+ Map<String, String> labelMap = new HashMap<String, String>();
+
+ NodeInfo node = new NodeInfo();
+
+ node.setIp(service.getAddress());
+ node.setPort(String.valueOf(service.getPort()));
+ node.setNodeId(service.getId());
+
+
+
+ try {
+
+ for (String tag : tagList) {
+
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ ms_url = (baseMap.get("url") == null ? "" : baseMap.get("url"));
+ ms_version = (baseMap.get("version") == null ? "" : baseMap.get("version"));
+ ms_protocol = (baseMap.get("protocol") == null ? "" : baseMap.get("protocol"));
+ ms_status = (baseMap.get("status") == null ? "1" : baseMap.get("status"));
+
+ if (baseMap.get("publish_port") != null) {
+ ms_publish_port = (baseMap.get("publish_port"));
+ }
+
+ if (baseMap.get("is_manual") != null) {
+ ms_is_manual = baseMap.get("is_manual");
+
+ }
+
+ if (baseMap.get("ha_role") != null) {
+ node.setHa_role(baseMap.get("ha_role"));
+ }
+
+ if (baseMap.get("host") != null) {
+ ms_host=baseMap.get("host");
+ }
+
+ if (baseMap.get("path") != null) {
+ ms_path=baseMap.get("path");
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"labels\"")) {
+ String ms_labels_json = "{"+tag.split("\"labels\":\\{")[1];
+ labelMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
+
+
+
+ for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) {
+ if ("visualRange".equals(labelEntry.getKey())) {
+ ms_visualRange = labelEntry.getValue();
+ } else if ("network_plane_type".equals(labelEntry.getKey())) {
+ ms_network_plane_type = labelEntry.getValue();
+ } else {
+ nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue());
+ }
+
+ }
+
+
+ continue;
+ }
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_namespace_json = tag.split("\"ns\":")[1];
+ Map<String, String> namespaceMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_namespace_json, Map.class);
+
+ if (namespaceMap.get("namespace") != null) {
+ nodeNamespace = namespaceMap.get("namespace");
+ } else {
+ nodeNamespace = "";
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"lb\"")) {
+ String ms_lb_json = tag.split("\"lb\":")[1];
+ Map<String, String> lbMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_lb_json, Map.class);
+
+ if (lbMap.get("lb_policy") != null) {
+ ms_lb_policy = lbMap.get("lb_policy");
+ if (ms_lb_policy.startsWith("hash") || ms_lb_policy.equals("ip_hash")) {
+ ms_lb_policy = "ip_hash";
+ }
+
+ }
+
+ if (lbMap.get("lb_server_params") != null) {
+ node.setLb_server_params(lbMap.get("lb_server_params").replace(" ", ","));
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"checks\"")) {
+ String ms_check_json = tag.split("\"checks\":")[1];
+ Map<String, String> checkMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class);
+
+
+ //自动注册健康检查
+ if (StringUtils.isNotBlank(checkMap.get("ttl"))){
+ node.setCheckType("TTL");
+ node.setTtl(checkMap.get("ttl"));
+ }
+ else if(StringUtils.isNotBlank(checkMap.get("http"))){
+ node.setCheckType("HTTP");
+ node.setCheckUrl(checkMap.get("http"));
+ if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval"));
+ if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout"));
+ }
+ else if(StringUtils.isNotBlank(checkMap.get("tcp"))){
+ node.setCheckType("TCP");
+ node.setCheckUrl(checkMap.get("tcp"));
+ if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval"));
+ if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout"));
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"metadata\"")) {
+ String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1];
+ Map<String, String> metadataMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class);
+
+
+
+ for (Map.Entry<String, String> entry : metadataMap.entrySet()) {
+ KeyVaulePair keyVaulePair = new KeyVaulePair();
+ keyVaulePair.setKey(entry.getKey());
+ keyVaulePair.setValue(entry.getValue());
+ ms_metadata.add(keyVaulePair);
+ }
+
+ continue;
+ }
+
+
+
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+ // 健康检查信息
+ List<Check> checks = healthService.getChecks();
+ node.setStatus("passing");
+ for (Check check : checks) {
+ if (!"passing".equals(check.getStatus())) {
+ node.setStatus(check.getStatus());
+ break;
+ }
+ }
+
+ if (!ms_version.equals(version)) {
+ continue;
+ }
+
+ // namespace过滤
+ if (!namespace.equals(nodeNamespace)) {
+ continue;
+ }
+
+ // 标签过滤
+ if (islabelQuery) {
+ boolean ifMatchLabel = false;
+ for (Map.Entry<String, String> query_entry : query_labelMap.entrySet()) {
+ String key = query_entry.getKey();
+ String value = query_entry.getValue();
+ if (StringUtils.isBlank(labelMap.get(key))) {
+ continue;
+ }
+
+ String[] queryTagArray = StringUtils.split(value, "|");
+ String[] serviceTagArray = StringUtils.split(labelMap.get(key), "|");
+ if (DiscoverUtil.contain(queryTagArray, serviceTagArray)) {
+ ifMatchLabel = true;
+ break;
+ }
+
+ }
+
+ if (!ifMatchLabel) {
+ continue;
+ }
+ }
+
+
+ nodes.add(node);
+ serviceLabels.addAll(nodeLabels);
+
+ microServiceInfo.setServiceName(serviceName);
+ microServiceInfo.setUrl(ms_url);
+ microServiceInfo.setVersion(ms_version);
+ microServiceInfo.setProtocol(ms_protocol);
+ microServiceInfo.setStatus(null);
+ microServiceInfo.setPublish_port(ms_publish_port);
+ microServiceInfo.setIs_manual(Boolean.parseBoolean(ms_is_manual));
+ microServiceInfo.setVisualRange(ms_visualRange);
+ microServiceInfo.setNetwork_plane_type(ms_network_plane_type);
+ microServiceInfo.setLb_policy(ms_lb_policy);
+ microServiceInfo.setHost(ms_host);
+ microServiceInfo.setPath(ms_path);
+
+ microServiceInfo.setMetadata(ms_metadata);
+ microServiceInfo.setNamespace(namespace);
+ microServiceInfo.setLabels(new ArrayList<String>(serviceLabels));
+ microServiceInfo.setNodes(nodes);
+
+ microServiceInfoList.add(microServiceInfo);
+ }
+
+
+
+ if (microServiceInfoList.size() == 0) {
+ String errInfo =
+ "microservice not found: serviceName-" + serviceName + ",version-" + version
+ + ",namespace-" + namespace + ",labels-" + labels;
+ throw new ExtendedNotFoundException(errInfo);
+ }
+
+
+
+
+
+ return microServiceInfoList;
+
+
+ } catch (ExtendedNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ExtendedInternalServerErrorException(e.getMessage());
+ }
+ }
+
+
+ private String getServiceName4Consul(String serviceName,String namespace){
+ String consul_serviceName;
+
+ if (StringUtils.isNotBlank(namespace)) {
+// if (DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT.equals(namespace)) {
+// consul_serviceName=serviceName;
+// }else{
+ consul_serviceName=serviceName+"-"+namespace;
+// }
+ }
+ else{
+ consul_serviceName=serviceName;
+ }
+ return consul_serviceName;
+ }
+
+
+
+
+
+
+ private void checkMicroServiceInfo(MicroServiceInfo microServiceInfo){
+
+ if (StringUtils.isBlank(microServiceInfo.getServiceName())
+ || StringUtils.isBlank(microServiceInfo.getProtocol())) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL: Some required fields are empty");
+ }
+
+ if(microServiceInfo.getNodes()==null || microServiceInfo.getNodes().size() == 0){
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL: Nodes fields are empty");
+ }
+
+ if (!RegExpTestUtil.serviceNameRegExpTest(microServiceInfo.getServiceName().trim())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:ServiceName("
+ + microServiceInfo.getServiceName() + ") format error");
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getHost())) {
+ if (!RegExpTestUtil.serviceNameRegExpTest(microServiceInfo.getHost().trim())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo host ("
+ + microServiceInfo.getHost() + ") format error");
+ }
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getLb_policy())) {
+ if (!DiscoverUtil.checkExist(DiscoverUtil.LB_POLICY_LIST, microServiceInfo.getLb_policy()
+ .trim(), ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:lb_policy is wrong,value range:("
+ + DiscoverUtil.LB_POLICY_LIST + ")");
+ }
+
+ }
+
+ if (StringUtils.isNotBlank(microServiceInfo.getVersion())) {
+ if (!RegExpTestUtil.versionRegExpTest(microServiceInfo.getVersion())) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:version is not a valid format");
+
+ }
+ }
+
+
+
+ if (StringUtils.isNotBlank(microServiceInfo.getUrl())) {
+
+ String url=microServiceInfo.getUrl();
+ if(!"/".equals(url)){
+ if(!url.startsWith("/")){
+ url="/"+url;
+ microServiceInfo.setUrl(url);
+ }
+
+ if(url.endsWith("/")){
+ url=url.substring(0, url.length()-1);
+ microServiceInfo.setUrl(url);
+ }
+ }
+
+ if (!RegExpTestUtil.urlRegExpTest(url)) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:url ("+url+") is not a valid format");
+ }
+
+ }
+ else{
+ microServiceInfo.setUrl("/");
+ }
+
+
+ if (StringUtils.isNotBlank(microServiceInfo.getPath())) {
+
+ String path=microServiceInfo.getPath();
+ if(!"/".equals(path)){
+ if(!path.startsWith("/")){
+ path="/"+path;
+ microServiceInfo.setPath(path);
+ }
+
+ if(path.endsWith("/")){
+ path=path.substring(0, path.length()-1);
+ microServiceInfo.setPath(path);
+ }
+ }
+
+ if (!RegExpTestUtil.urlRegExpTest(path)) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:path ("+path+") is not a valid format");
+
+ }
+
+
+
+ }
+
+
+ for (Node node : microServiceInfo.getNodes()) {
+
+ if (StringUtils.isNotBlank(node.getIp())) {
+ if (!RegExpTestUtil.ipRegExpTest(node.getIp())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:IP(" + node.getIp()
+ + ")is not a valid ip address");
+ }
+ }
+
+ if (!RegExpTestUtil.portRegExpTest(node.getPort())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Port("
+ + node.getPort() + ")is not a valid Port address");
+ }
+
+
+ if (StringUtils.isNotBlank(node.getLb_server_params())) {
+ try {
+ String[] lb_server_params_array = node.getLb_server_params().split(",");
+ for (int i = 0; i < lb_server_params_array.length; i++) {
+ String params = lb_server_params_array[i].split("=")[0];
+ if (!DiscoverUtil.checkExist(DiscoverUtil.LB_PARAMS_LIST, params, ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:lb_server_params is wrong:"
+ + lb_server_params_array[i]);
+ }
+ }
+ } catch (Exception e) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:lb_server_params'format is wrong:"
+ + node.getLb_server_params());
+ }
+
+ }
+
+ if (StringUtils.isNotBlank(node.getCheckType())) {
+ if (!DiscoverUtil.checkExist(DiscoverUtil.CHECK_TYPE_LIST, node.getCheckType().trim(), ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:checkType is wrong,value range:("
+ + DiscoverUtil.CHECK_TYPE_LIST + ")");
+ }
+
+
+ if ("HTTP".equals(node.getCheckType()) || "TCP".equals(node.getCheckType())) {
+ String checkUrl=node.getCheckUrl();
+ if (StringUtils.isBlank(checkUrl)) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:checkUrl field is empty");
+ }
+
+ if("HTTP".equals(node.getCheckType())){
+
+
+ if(RegExpTestUtil.httpUrlRegExpTest(checkUrl)){
+ if(!checkUrl.startsWith("http://")){
+ checkUrl="http://"+checkUrl;
+ node.setCheckUrl(checkUrl);
+ }
+ }
+ else{
+ if(!checkUrl.startsWith("/")){
+ checkUrl="/"+checkUrl;
+ }
+ checkUrl="http://"+node.getIp()+":"+node.getPort()+checkUrl;
+ node.setCheckUrl(checkUrl);
+ }
+ }
+
+
+ }
+
+ }
+
+ if (StringUtils.isNotBlank(node.getHa_role())) {
+ if (!DiscoverUtil
+ .checkExist(DiscoverUtil.CHECK_HA_ROLE_LIST, node.getHa_role().trim(), ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:ha_role is wrong,value range:("
+ + DiscoverUtil.CHECK_HA_ROLE_LIST + ")");
+ }
+ }
+
+
+ }
+
+
+
+ String[] visualRangeArray = StringUtils.split(microServiceInfo.getVisualRange(), "|");
+ for (int i = 0; i < visualRangeArray.length; i++) {
+ if (!DiscoverUtil.checkExist(DiscoverUtil.VISUAL_RANGE_LIST, visualRangeArray[i], ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:type is wrong,value range:("
+ + DiscoverUtil.VISUAL_RANGE_LIST + ")");
+ }
+ }
+
+ microServiceInfo.setProtocol(microServiceInfo.getProtocol().toUpperCase());
+ if (!DiscoverUtil.checkExist(DiscoverUtil.PROTOCOL_LIST, microServiceInfo.getProtocol().trim(),
+ ",")) {
+ throw new UnprocessableEntityException(
+ "register MicroServiceInfo FAIL:Protocol is wrong,value range:("
+ + DiscoverUtil.PROTOCOL_LIST + ")");
+ }
+
+ if (microServiceInfo.getLabels()!=null) {
+ for (String label : microServiceInfo.getLabels()) {
+ if (!RegExpTestUtil.labelRegExpTest(label)) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:label[" + label
+ + "] is not a valid format(key:value)");
+ }
+ }
+ }
+
+
+
+ // 判断自定义发布端口
+ if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) {
+
+ if(DiscoverUtil.checkExist(DiscoverUtil.HTTP_PROTOCOL, microServiceInfo.getProtocol())){
+
+ if(microServiceInfo.getPublish_port().contains("|")){
+
+ String[] publishPortArray = StringUtils.split(microServiceInfo.getPublish_port(), "|");
+
+ int portNum=publishPortArray.length;
+
+ //判断端口格式
+ for (int i = 0; i < portNum; i++) {
+ if (!RegExpTestUtil.portRegExpTest(publishPortArray[i])) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port("
+ +publishPortArray[i] + ")is not a valid Port address");
+ }
+ }
+
+ //判断端口数量
+ if(portNum==0 || portNum>2){
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port num is wrong:"+portNum);
+ }
+ else if(portNum==2){
+ //判断端口值是否一样
+ if(publishPortArray[0].equals(publishPortArray[1])){
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Two ports have the same value :"+publishPortArray[0]);
+ }
+ }
+ else if(portNum==1){
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Two ports have one null value");
+ }
+ }
+ else{
+ if (!RegExpTestUtil.portRegExpTest(microServiceInfo.getPublish_port())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port("
+ + microServiceInfo.getPublish_port() + ")is not a valid Port address");
+ }
+ }
+
+ }
+ else if("TCP".equals(microServiceInfo.getProtocol()) || "UDP".equals(microServiceInfo.getProtocol())){
+ if (!RegExpTestUtil.portRegExpTest(microServiceInfo.getPublish_port())) {
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port("
+ + microServiceInfo.getPublish_port() + ")is not a valid Port address");
+ }
+
+ int tcpUdpPortRangeStart= Integer.parseInt(ConfigUtil.getInstance().getTcpudpPortRangeStart());
+ int tcpUdpPortRangeEnd= Integer.parseInt(ConfigUtil.getInstance().getTcpudpPortRangeEnd());
+ int iPublishPort=Integer.parseInt(microServiceInfo.getPublish_port());
+
+ if(iPublishPort>tcpUdpPortRangeEnd || iPublishPort <tcpUdpPortRangeStart){
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public_Port Range ("
+ + tcpUdpPortRangeStart + "-"+tcpUdpPortRangeEnd+")");
+ }
+
+ }
+ else{
+ microServiceInfo.setPublish_port("");
+ }
+
+
+
+
+
+ }
+
+ //检查同名不同协议注册
+ try{
+ List<MicroServiceFullInfo> serviceList= getMicroServiceForNodes(microServiceInfo.getServiceName(),microServiceInfo.getVersion(), false,"",microServiceInfo.getNamespace());
+ if(serviceList!=null && serviceList.size()>0){
+ for(MicroServiceFullInfo service:serviceList){
+ if(!service.getProtocol().equalsIgnoreCase(microServiceInfo.getProtocol())){
+ throw new UnprocessableEntityException("register MicroServiceInfo FAIL:There is a same service ,but different protocol--"
+ + service.getProtocol());
+ }
+
+ }
+ }
+ }
+ catch(ExtendedNotFoundException e){
+// LOGGER.info("register MicroServiceInfo CHECK ok for protocol:service is not fond");
+ }
+
+
+ }
+
+
+ private void checkServiceNameAndVersion(String serviceName,String version){
+ if (StringUtils.isBlank(serviceName)) {
+ throw new UnprocessableEntityException(
+ "check MicroServiceInfo FAIL:serviceName can't be empty");
+ }
+
+ if (!RegExpTestUtil.serviceNameRegExpTest(serviceName)) {
+ throw new UnprocessableEntityException("check MicroServiceInfo FAIL:ServiceName("
+ + serviceName + ") format error");
+ }
+
+ if (StringUtils.isNotBlank(version)) {
+ if (!RegExpTestUtil.versionRegExpTest(version)) {
+ throw new UnprocessableEntityException(
+ "check MicroServiceInfo FAIL:version is not a valid format");
+ }
+ }
+ }
+
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java
new file mode 100644
index 0000000..a6e1037
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java
@@ -0,0 +1,875 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.core.KeyVaulePair;
+import org.onap.msb.sdclient.core.MicroServiceFullInfo;
+import org.onap.msb.sdclient.core.NodeInfo;
+import org.onap.msb.sdclient.core.PublishAddress;
+import org.onap.msb.sdclient.core.PublishFullAddress;
+import org.onap.msb.sdclient.core.exception.ExtendedNotFoundException;
+import org.onap.msb.sdclient.core.exception.UnprocessableEntityException;
+import org.onap.msb.sdclient.wrapper.util.DiscoverUtil;
+import org.onap.msb.sdclient.wrapper.util.RegExpTestUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PublishAddressWrapper {
+
+ private static PublishAddressWrapper instance = new PublishAddressWrapper();
+
+
+ private PublishAddressWrapper() {}
+
+ public static PublishAddressWrapper getInstance() {
+ return instance;
+ }
+
+ private final String ROUTE_DEFAULT_WAY = "ip";
+
+ private final String ROUTE_IP = "ip";
+
+ private final String ROUTE_DOMAIN = "domain";
+
+ private final String ROUTE_DEFAULT_SUBDOMAIN = "openpalette.zte.com.cn";
+
+ private final String METADATA_ROUTE_WAY = "routeWay";
+
+ private final String METADATA_ROUTE_SUBDOMAIN = "routeSubdomain";
+
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PublishAddressWrapper.class);
+
+ public static volatile Map<String, List<MicroServiceFullInfo>> publishApigateWayList =
+ new HashMap<String, List<MicroServiceFullInfo>>();
+
+ private ConsulClientApp consulClientApp;
+
+
+ ExecutorService exec = Executors.newCachedThreadPool();
+
+
+ public void setConsulClientApp(ConsulClientApp consulClientApp) {
+ this.consulClientApp = consulClientApp;
+ }
+
+
+
+ /**
+ * @Title getAllPublishaddress
+ * @Description TODO(get all publishaddresss list by service,rest-interface master methods)
+ * @param serviceName
+ * @param version
+ * @param namespace
+ * @param visualRange
+ * @return
+ * @return List<PublishFullAddress>
+ */
+ public Set<PublishFullAddress> getAllPublishaddress(String serviceName, String version,
+ String namespace, String visualRange) {
+
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+
+ // 1.Check input parameter format efficacy
+ checkServiceInputFormat(serviceName, version, visualRange);
+
+
+
+ // 2.get service Info
+ MicroServiceFullInfo serviceInfo =
+ ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version, namespace);
+
+ if (!DiscoverUtil.checkExist(DiscoverUtil.PUBLISH_PROTOCOL, serviceInfo.getProtocol())) {
+ throw new ExtendedNotFoundException("This service's Protocol (" + serviceInfo.getProtocol()
+ + ") is not published to apigateway");
+ }
+
+ if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) {
+ if (StringUtils.isBlank(serviceInfo.getPublish_port())) {
+ throw new ExtendedNotFoundException("This service's Protocol ("
+ + serviceInfo.getProtocol() + ") is not published to apigateway");
+ }
+ }
+
+ Set<PublishFullAddress> publishFullAddressList = new HashSet<PublishFullAddress>();
+
+ // 3.get in-system apigateway publish address (visualRange=1)
+ if (DiscoverUtil.checkVisualRangeIn(visualRange)) {
+ Set<PublishFullAddress> publishFullAddressInList =
+ getPublishFullAddress(namespace, DiscoverUtil.VISUAL_RANGE_IN, serviceInfo);
+ if (publishFullAddressInList != null && publishFullAddressInList.size() > 0) {
+ publishFullAddressList.addAll(publishFullAddressInList);
+ }
+
+ }
+
+ // 4.get out-system apigateway publish address (visualRange=0)
+ if (DiscoverUtil.checkVisualRangeOut(visualRange)) {
+ Set<PublishFullAddress> publishFullAddressOutList =
+ getPublishFullAddress(namespace, DiscoverUtil.VISUAL_RANGE_OUT, serviceInfo);
+ if (publishFullAddressOutList != null && publishFullAddressOutList.size() > 0) {
+ publishFullAddressList.addAll(publishFullAddressOutList);
+ }
+ }
+
+ if (publishFullAddressList.size() > 0) {
+ return publishFullAddressList;
+ }
+
+ throw new ExtendedNotFoundException("This service's publish Address is not found");
+ }
+
+ /**
+ * @Title getApigatewayServiceInfo
+ * @Description TODO(get one apigatewayServiceInfo by namespace,rest-interface master methods)
+ * @param namespace
+ * @param visualRange
+ * @return
+ * @return List<MicroServiceFullInfo>
+ */
+ public Set<MicroServiceFullInfo> getApigatewayServiceInfo(String namespace, String visualRange) {
+
+ if (!DiscoverUtil.checkExist(DiscoverUtil.VISUAL_RANGE_LIST, visualRange, ",")) {
+ throw new UnprocessableEntityException(
+ "get ApigatewayServiceInfo FAIL:visualRange is wrong,value range:("
+ + DiscoverUtil.VISUAL_RANGE_LIST + ")");
+ }
+
+ List<MicroServiceFullInfo> apigatewayList;
+
+ if (DiscoverUtil.checkVisualRangeIn(visualRange)) {
+ apigatewayList = getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, namespace);
+
+ } else {
+ apigatewayList = getApiGateWayFromCache(DiscoverUtil.ROUTER_SERVINCE, namespace);
+
+ if (apigatewayList != null) {
+ if (StringUtils.isNotBlank(System.getenv("ROUTER_IP"))) {
+ for (MicroServiceFullInfo routerInfo : apigatewayList) {
+ for (NodeInfo node : routerInfo.getNodes()) {
+ node.setIp(System.getenv("ROUTER_IP"));
+ }
+
+ }
+ }
+ }
+ }
+
+
+ if (apigatewayList == null || apigatewayList.isEmpty()) {
+ throw new ExtendedNotFoundException("This service's publish Address is not found");
+ }
+ else{
+ Set<MicroServiceFullInfo> apigatewaySet= new HashSet<MicroServiceFullInfo>(apigatewayList);
+ return apigatewaySet;
+ }
+
+
+
+ }
+
+
+
+ /**
+ * @Title convert2PublishFullAddress
+ * @Description TODO(convert to PublishFullAddress from MicroServiceFullInfo )
+ * @param apigatewayInfo
+ * @param serviceInfo
+ * @return List<PublishFullAddress>
+ */
+ private List<PublishFullAddress> convert2PublishFullAddress(MicroServiceFullInfo apigatewayInfo,
+ MicroServiceFullInfo serviceInfo) {
+
+ List<PublishFullAddress> publishFullAddressList = new ArrayList<PublishFullAddress>();
+
+
+
+ String routeWay = this.ROUTE_DEFAULT_WAY, routeSubdomain = this.ROUTE_DEFAULT_SUBDOMAIN;
+
+ List<KeyVaulePair> metadata = apigatewayInfo.getMetadata();
+ if (metadata != null) {
+
+ for (KeyVaulePair keyVaulePair : metadata) {
+ if (this.METADATA_ROUTE_WAY.equals(keyVaulePair.getKey())) {
+ routeWay = keyVaulePair.getValue();
+ }
+ if (this.METADATA_ROUTE_SUBDOMAIN.equals(keyVaulePair.getKey())) {
+ routeSubdomain = keyVaulePair.getValue();
+ }
+ }
+ }
+
+ NodeInfo apigatewayNode = (NodeInfo) apigatewayInfo.getNodes().toArray()[0];
+
+ String[] routeWays = StringUtils.split(routeWay, DiscoverUtil.SPLIT_LINE);
+ for (int i = 0; i < routeWays.length; i++) {
+ PublishFullAddress publishFullAddress = new PublishFullAddress();
+ // set service publish visualRange
+ publishFullAddress.setVisualRange(apigatewayInfo.getVisualRange());
+ if (this.ROUTE_IP.equals(routeWays[i])) {
+ // ----routeWay:ip-----
+
+ // set service publish ip
+ publishFullAddress.setIp(apigatewayNode.getIp());
+ if (DiscoverUtil.VISUAL_RANGE_OUT.equals(apigatewayInfo.getVisualRange())) {
+ if (StringUtils.isNotBlank(System.getenv("ROUTER_IP"))) {
+ publishFullAddress.setIp(System.getenv("ROUTER_IP"));
+ }
+ }
+
+
+
+ // set service publish url
+ publishFullAddress.setPublish_url(getPublishUrl4IP(serviceInfo));
+
+ // set service port
+ if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) {
+ publishFullAddress.setPort(apigatewayNode.getPort());
+ publishFullAddress.setPublish_protocol("http");
+ publishFullAddressList.add(publishFullAddress);
+ }
+ else{
+
+ String[] publishPorts =
+ StringUtils.split(serviceInfo.getPublish_port(), DiscoverUtil.SPLIT_LINE);
+ if (publishPorts.length == 2) {
+ // multiPublishPort: https|http
+ publishFullAddress.setPort(publishPorts[0]);
+ publishFullAddress.setPublish_protocol("https");
+ publishFullAddressList.add(publishFullAddress);
+
+
+ PublishFullAddress publishFullAddress2 =
+ new PublishFullAddress(publishFullAddress.getIp(), publishPorts[1],
+ publishFullAddress.getPublish_url(), publishFullAddress.getVisualRange(), "http");
+ publishFullAddressList.add(publishFullAddress2);
+
+ } else {
+ // single Port
+
+ if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) {
+ publishFullAddress.setPort(serviceInfo.getPublish_port());
+ publishFullAddress.setPublish_protocol("https");
+ } else {
+ publishFullAddress.setPort(apigatewayNode.getPort());
+ publishFullAddress.setPublish_protocol("http");
+ }
+
+ if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) {
+ publishFullAddress.setPublish_protocol(serviceInfo.getProtocol());
+ }
+
+ publishFullAddressList.add(publishFullAddress);
+
+ }
+ }
+
+
+ } else if (this.ROUTE_DOMAIN.equals(routeWays[i])) {
+ // ----routeWay:domain-----
+
+ // set service domain
+ String host = getHost4Domain(serviceInfo);
+ publishFullAddress.setDomain(host + "." + routeSubdomain);
+
+
+ if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) {
+ publishFullAddress.setPort(serviceInfo.getPublish_port());
+ publishFullAddress.setPublish_protocol(serviceInfo.getProtocol());
+ } else {
+ publishFullAddress.setPublish_protocol("http");
+ publishFullAddress.setPort(apigatewayNode.getPort());
+ }
+
+ // set service publish url
+ publishFullAddress.setPublish_url(getPublishUrl4Domain(serviceInfo));
+
+
+ publishFullAddressList.add(publishFullAddress);
+ }
+
+
+
+ }
+
+ return publishFullAddressList;
+ }
+
+
+ /**
+ * @Title getPublishFullAddress
+ * @Description TODO(get PublishFullAddress List for namespace and visualRange)
+ * @param namespace
+ * @param visualRange
+ * @param serviceInfo
+ * @return List<PublishFullAddress>
+ */
+ private Set<PublishFullAddress> getPublishFullAddress(String namespace, String visualRange,
+ MicroServiceFullInfo serviceInfo) {
+
+ if (DiscoverUtil.checkVisualRangeIn(visualRange)) {
+ if (!DiscoverUtil.checkVisualRangeIn(serviceInfo.getVisualRange())) {
+ return null;
+ }
+ } else {
+ if (!DiscoverUtil.checkVisualRangeOut(serviceInfo.getVisualRange())) {
+ return null;
+ }
+ }
+
+
+ Set<PublishFullAddress> publishFullAddressList = new HashSet<PublishFullAddress>();
+ List<MicroServiceFullInfo> apigatewayList = getApigatewayInfo4Service(namespace, visualRange);
+ if (apigatewayList != null && !apigatewayList.isEmpty()) {
+ for (MicroServiceFullInfo apigatewayInfo : apigatewayList) {
+ if (isPublish2apigateway(apigatewayInfo, serviceInfo)) {
+ publishFullAddressList.addAll(convert2PublishFullAddress(apigatewayInfo, serviceInfo));
+ }
+ }
+ }
+ return publishFullAddressList;
+ }
+
+
+
+ private String getHost4Domain(MicroServiceFullInfo serviceInfo) {
+ String host = "";
+ if (StringUtils.isNotBlank(serviceInfo.getHost())) {
+ host = serviceInfo.getHost();
+ } else {
+ if (StringUtils.isNotBlank(serviceInfo.getNamespace())) {
+ host =
+ serviceInfo.getServiceName() + DiscoverUtil.SERVICENAME_LINE_NAMESPACE
+ + serviceInfo.getNamespace();
+ } else {
+ host = serviceInfo.getServiceName();
+ }
+ }
+
+ return host;
+ }
+
+ private String getPublishPort(MicroServiceFullInfo apigatewayInfo,
+ MicroServiceFullInfo serviceInfo) {
+
+ NodeInfo node = (NodeInfo) apigatewayInfo.getNodes().toArray()[0];
+ String port = "";
+
+ if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) {
+ return serviceInfo.getPublish_port();
+ }
+
+ if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) {
+ port = node.getPort();
+ } else {
+ if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) {
+ port = serviceInfo.getPublish_port();
+ } else {
+ port = node.getPort();
+ }
+ }
+
+ return port;
+
+ }
+
+
+
+ private String getPublishUrl4Domain(MicroServiceFullInfo serviceInfo) {
+ String publish_url = "/";
+ if (StringUtils.isNotBlank(serviceInfo.getPath()) && !"/".equals(serviceInfo.getPath())) {
+ publish_url = serviceInfo.getPath();
+ } else {
+ publish_url = serviceInfo.getUrl();
+ }
+ return publish_url;
+ }
+
+ private String getPublishUrl4IP(MicroServiceFullInfo serviceInfo) {
+
+ String publish_url = "/";
+ if (StringUtils.isNotBlank(serviceInfo.getPath()) && !"/".equals(serviceInfo.getPath())) {
+ publish_url = serviceInfo.getPath();
+ } else {
+ String versionUrl = "";
+ String serviceNameUrl = serviceInfo.getServiceName();
+
+ if (StringUtils.isNotBlank(serviceInfo.getVersion())) {
+ versionUrl = "/" + serviceInfo.getVersion();
+ }
+ switch (serviceInfo.getProtocol()) {
+ case "REST":
+ publish_url = "/api/" + serviceNameUrl + versionUrl;
+ break;
+ case "UI":
+ publish_url = "/iui/" + serviceNameUrl;
+ break;
+ case "HTTP":
+ publish_url = "/" + serviceNameUrl + versionUrl;
+ break;
+ case "PORTAL":
+ publish_url = "/" + serviceNameUrl + versionUrl;
+ break;
+ case "TCP":
+ publish_url = serviceInfo.getUrl();
+ break;
+ case "UDP":
+ publish_url = serviceInfo.getUrl();
+ break;
+ }
+ }
+
+ return publish_url;
+ }
+
+
+ private void checkServiceInputFormat(String serviceName, String version, String visualRange) {
+ if (StringUtils.isBlank(serviceName)) {
+ throw new UnprocessableEntityException("serviceName can't be empty");
+ }
+
+ if (!RegExpTestUtil.serviceNameRegExpTest(serviceName)) {
+ throw new UnprocessableEntityException("get MicroServiceInfo FAIL:ServiceName("
+ + serviceName + ") format error");
+ }
+
+ if (StringUtils.isNotBlank(version)) {
+ if (!RegExpTestUtil.versionRegExpTest(version)) {
+ throw new UnprocessableEntityException("version (" + version + ") is not a valid format");
+ }
+ }
+
+ if (!DiscoverUtil.checkVisualRangeIn(visualRange)
+ && !DiscoverUtil.checkVisualRangeOut(visualRange)) {
+ throw new UnprocessableEntityException(
+ "get ApigatewayServiceInfo FAIL:visualRange is wrong,value range:("
+ + DiscoverUtil.VISUAL_RANGE_LIST + ")");
+ }
+ }
+
+
+ /**
+ * @Title getApigatewayInfo4Service
+ * @Description TODO(get apigatewayServiceInfo List by namespaces[all & service-namespace])
+ * @param namespace
+ * @param visualRange
+ * @return
+ * @return List<MicroServiceFullInfo>
+ */
+ private List<MicroServiceFullInfo> getApigatewayInfo4Service(String namespace, String visualRange) {
+
+ String apigatewayName;
+ if (DiscoverUtil.checkVisualRangeIn(visualRange)) {
+ apigatewayName = DiscoverUtil.APIGATEWAY_SERVINCE;
+ } else {
+ apigatewayName = DiscoverUtil.ROUTER_SERVINCE;
+ }
+
+
+ String apigateway_ns;
+ if (StringUtils.isBlank(namespace)) {
+ apigateway_ns = DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT;
+ } else {
+ apigateway_ns = namespace;
+ }
+
+ String[] apigateway_ns_array = {DiscoverUtil.APIGATEWAY_SERVINCE_ALL, apigateway_ns};
+ List<MicroServiceFullInfo> apigatewayList4Service = new ArrayList<MicroServiceFullInfo>();
+ for (int i = 0; i < apigateway_ns_array.length; i++) {
+ List<MicroServiceFullInfo> apigatewayList =
+ getApiGateWayFromCache(apigatewayName, apigateway_ns_array[i]);
+ if (apigatewayList != null) {
+ apigatewayList4Service.addAll(apigatewayList);
+ }
+ }
+
+ return apigatewayList4Service;
+
+ }
+
+
+ private boolean isPublish2apigateway(MicroServiceFullInfo apigatewayInfo,
+ MicroServiceFullInfo serviceInfo) {
+ return isPublishByNetwork_plane_typeMatches(apigatewayInfo.getNetwork_plane_type(),
+ serviceInfo.getNetwork_plane_type())
+ && isPublishByRouteLabels(apigatewayInfo.getLabels(), serviceInfo.getLabels());
+ }
+
+ /**
+ * Determine whether the service needs to publish to apigateway TODO: according to the
+ * service_network_plane filter conditions
+ *
+ * @param String
+ * @return
+ */
+
+ private boolean isPublishByNetwork_plane_typeMatches(String apigateway_network_plane,
+ String service_network_plane) {
+
+ if (StringUtils.isBlank(apigateway_network_plane))
+ return true;
+ String[] routeNetwork_plane_typeArray = StringUtils.split(apigateway_network_plane, "|");
+ String[] serviceVisualRangeArray = StringUtils.split(service_network_plane, "|");
+ if (DiscoverUtil.contain(serviceVisualRangeArray, routeNetwork_plane_typeArray)) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Determine whether the service needs to publish to apigateway TODO: according to the labels
+ * filter conditions
+ *
+ * @param labelMap
+ * @return
+ */
+ private boolean isPublishByRouteLabels(List<String> apigatewayLabels, List<String> serviceLabels) {
+ if (apigatewayLabels == null || apigatewayLabels.isEmpty()) {
+ return true;
+ }
+
+ Map<String, String> apigateway_labelMap = new HashMap<String, String>();
+ Map<String, String> service_labelMap = new HashMap<String, String>();
+ for (String label : apigatewayLabels) {
+ String[] labelArray = label.split(":");
+ apigateway_labelMap.put(labelArray[0], labelArray[1]);
+ }
+
+ for (String label : serviceLabels) {
+ String[] labelArray = label.split(":");
+ service_labelMap.put(labelArray[0], labelArray[1]);
+ }
+
+ for (Map.Entry<String, String> entry : apigateway_labelMap.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+
+ // Multiple values match
+ String[] routeLalelsArray = StringUtils.split(value, "|");
+ if (StringUtils.isBlank(service_labelMap.get(key))) {
+ continue;
+ }
+
+ String[] serviceLabelsArray = StringUtils.split(service_labelMap.get(key), "|");
+
+ if (DiscoverUtil.contain(routeLalelsArray, serviceLabelsArray)) {
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+
+
+ private List<MicroServiceFullInfo> getApiGateWayFromCache(String apigatewayName,
+ String apigatewayNamespace) {
+ String apigatewayConsulName =
+ apigatewayName + DiscoverUtil.SERVICENAME_LINE_NAMESPACE + apigatewayNamespace;
+ if (publishApigateWayList.get(apigatewayConsulName) == null) {
+
+ try {
+ List<MicroServiceFullInfo> apigatewayList =
+ ConsulServiceWrapper.getInstance().getMicroServiceForNodes(apigatewayName, "v1", true,
+ "", apigatewayNamespace);
+ if (!apigatewayList.isEmpty()) {
+ consulClientApp.startHealthNodeListen(apigatewayConsulName);
+ return apigatewayList;
+ }
+ } catch (ExtendedNotFoundException e) {
+ LOGGER.warn("ApiGateWay Info not found:[serviceName]" + apigatewayName + ",[namespace]"
+ + apigatewayNamespace);
+ }
+
+ } else {
+ return publishApigateWayList.get(apigatewayConsulName);
+ }
+
+ return null;
+ }
+
+
+ public PublishAddress getPublishaddress(String serviceName, String version, String namespace,
+ int wait) {
+ if ("null".equals(version)) {
+ version = "";
+ }
+
+ // 1.Check input parameter format efficacy
+ checkServiceInputFormat(serviceName, version, DiscoverUtil.VISUAL_RANGE_IN);
+
+
+ MicroServiceFullInfo microServiceFullInfo =
+ ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version, namespace);
+
+ if (!DiscoverUtil.checkVisualRangeIn(microServiceFullInfo.getVisualRange())) {
+ throw new ExtendedNotFoundException("This service is not published internally");
+ }
+
+ if (!DiscoverUtil.checkExist(DiscoverUtil.PUBLISH_PROTOCOL, microServiceFullInfo.getProtocol())) {
+ throw new ExtendedNotFoundException("This service's Protocol ("
+ + microServiceFullInfo.getProtocol() + ") is not published to apigateway");
+ }
+
+ List<PublishAddress> publishaddress_all = new ArrayList<PublishAddress>();
+ List<PublishAddress> publishaddress_ns = new ArrayList<PublishAddress>();
+
+ List<MicroServiceFullInfo> apigatewayList_in_all =
+ getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, "all");
+ if (apigatewayList_in_all != null && !apigatewayList_in_all.isEmpty()) {
+ for (MicroServiceFullInfo apigateway : apigatewayList_in_all) {
+ if (isPublish2apigateway(apigateway, microServiceFullInfo)) {
+ publishaddress_all.add(convert2PublishAddress(apigateway, microServiceFullInfo));
+ }
+ }
+ }
+
+
+
+ String apigateway_ns;
+ if (StringUtils.isBlank(namespace)) {
+ apigateway_ns = DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT;
+ } else {
+ apigateway_ns = namespace;
+ }
+
+ List<MicroServiceFullInfo> apigatewayList_in_ns =
+ getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, apigateway_ns);
+ if (apigatewayList_in_ns != null && !apigatewayList_in_ns.isEmpty()) {
+ for (MicroServiceFullInfo apigateway : apigatewayList_in_ns) {
+ if (isPublish2apigateway(apigateway, microServiceFullInfo)) {
+ publishaddress_ns.add(convert2PublishAddress(apigateway, microServiceFullInfo));
+ }
+ }
+ }
+
+
+
+ // 即时返回
+ if (wait < 5) {
+ if (publishaddress_ns.size() > 0) {
+ return publishaddress_ns.get(0);
+ } else if (publishaddress_all.size() > 0) {
+ return publishaddress_all.get(0);
+ }
+
+
+ throw new ExtendedNotFoundException("This service's publish address is not found");
+ }
+
+ if (wait > 300) {
+ wait = 300;
+ }
+
+
+ // get service publish url
+ String publish_url = "/";
+ if (StringUtils.isNotBlank(microServiceFullInfo.getPath())) {
+ publish_url = microServiceFullInfo.getPath();
+ } else {
+ String versionUrl = "";
+ String serviceNameUrl = microServiceFullInfo.getServiceName();
+
+
+ if (StringUtils.isNotBlank(microServiceFullInfo.getVersion())) {
+ versionUrl = "/" + microServiceFullInfo.getVersion();
+ }
+ switch (microServiceFullInfo.getProtocol()) {
+ case "REST":
+ publish_url = "/api/" + serviceNameUrl + versionUrl;
+ break;
+ case "UI":
+ publish_url = "/iui/" + serviceNameUrl;
+ break;
+ case "HTTP":
+ publish_url = "/" + serviceNameUrl + versionUrl;
+ break;
+ case "TCP":
+ publish_url = microServiceFullInfo.getUrl();
+ break;
+ case "UDP":
+ publish_url = microServiceFullInfo.getUrl();
+ break;
+ }
+ }
+
+ // 延迟监听返回
+ Future<PublishAddress> f = exec.submit(new TimeTask(namespace, publish_url));
+ try {
+ return f.get(wait, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ LOGGER.error(e.getMessage());
+ } catch (ExecutionException e) {
+ // TODO Auto-generated catch block
+ LOGGER.error(e.getMessage());
+ } catch (TimeoutException e) {
+ // 定义超时后的状态修改
+ // LOGGER.error(e.getMessage());
+ LOGGER.error(e.getMessage());
+ } finally {
+
+ f.cancel(true);
+ }
+
+ if (publishaddress_ns.size() > 0) {
+ return publishaddress_ns.get(0);
+ } else if (publishaddress_all.size() > 0) {
+ return publishaddress_all.get(0);
+ }
+
+ throw new ExtendedNotFoundException("This service's apigatewayInfo is not found");
+
+ }
+
+
+ private PublishAddress convert2PublishAddress(MicroServiceFullInfo apigatewayInfo,
+ MicroServiceFullInfo serviceInfo) {
+ PublishAddress publishAddress = new PublishAddress();
+
+ NodeInfo node = (NodeInfo) apigatewayInfo.getNodes().toArray()[0];
+ publishAddress.setIp(node.getIp());
+
+ if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) {
+ publishAddress.setPort(node.getPort());
+ } else {
+ if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) {
+ publishAddress.setPort(serviceInfo.getPublish_port());
+ } else {
+ publishAddress.setPort(node.getPort());
+ }
+ }
+
+
+ // get service publish url
+ String publish_url = "/";
+ if (StringUtils.isNotBlank(serviceInfo.getPath())) {
+ publish_url = serviceInfo.getPath();
+ } else {
+ String versionUrl = "";
+ String serviceNameUrl = serviceInfo.getServiceName();
+
+
+ if (StringUtils.isNotBlank(serviceInfo.getVersion())) {
+ versionUrl = "/" + serviceInfo.getVersion();
+ }
+ switch (serviceInfo.getProtocol()) {
+ case "REST":
+ publish_url = "/api/" + serviceNameUrl + versionUrl;
+ break;
+ case "UI":
+ publish_url = "/iui/" + serviceNameUrl;
+ break;
+ case "HTTP":
+ publish_url = "/" + serviceNameUrl + versionUrl;
+ break;
+ case "TCP":
+ publish_url = serviceInfo.getUrl();
+ break;
+ case "UDP":
+ publish_url = serviceInfo.getUrl();
+ break;
+ }
+ }
+
+ publishAddress.setPublish_url(publish_url);
+
+
+ return publishAddress;
+ }
+
+
+
+ public class TimeTask implements Callable<PublishAddress> {
+
+ private String namespace;
+ private String publish_url;
+
+ @Override
+ public PublishAddress call() throws Exception {
+
+
+ while (true) {
+ List<PublishAddress> oldAddress = getApigatewayListFromCache(namespace, publish_url);
+
+
+ Thread.sleep(2000);
+ // LOGGER.info("oldAddress:"+oldAddress);
+ List<PublishAddress> newAddress = getApigatewayListFromCache(namespace, publish_url);
+ if (!oldAddress.equals(newAddress)) {
+ // LOGGER.info("CHANGED:"+oldAddress+"-"+apigatewayAddress);
+
+ return newAddress.get(0);
+ }
+ }
+
+ }
+
+ TimeTask(String namespace, String publish_url) {
+ this.namespace = namespace;
+ this.publish_url = publish_url;
+ }
+
+ }
+
+ private List<PublishAddress> getApigatewayListFromCache(String namespace, String publish_url) {
+ List<PublishAddress> fullAddress = new ArrayList<PublishAddress>();
+ String apigatewayName4ns =
+ DiscoverUtil.APIGATEWAY_SERVINCE + DiscoverUtil.SERVICENAME_LINE_NAMESPACE + namespace;
+ if (publishApigateWayList.get(apigatewayName4ns) != null) {
+ List<MicroServiceFullInfo> publishaddress4ns = publishApigateWayList.get(apigatewayName4ns);
+ for (MicroServiceFullInfo address : publishaddress4ns) {
+ NodeInfo node = (NodeInfo) address.getNodes().toArray()[0];
+ fullAddress.add(new PublishAddress(node.getIp(), node.getPort(), publish_url));
+ }
+
+ } else {
+ if (publishApigateWayList.get(DiscoverUtil.APIGATEWAY_SERVINCE_ALL) != null) {
+ List<MicroServiceFullInfo> publishaddress4all =
+ publishApigateWayList.get(DiscoverUtil.APIGATEWAY_SERVINCE_ALL);
+ for (MicroServiceFullInfo address : publishaddress4all) {
+ NodeInfo node = (NodeInfo) address.getNodes().toArray()[0];
+ fullAddress.add(new PublishAddress(node.getIp(), node.getPort(), publish_url));
+ }
+ }
+ }
+
+ return fullAddress;
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java
new file mode 100644
index 0000000..db12cb6
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java
@@ -0,0 +1,281 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+
+import org.onap.msb.sdclient.wrapper.consul.util.Jackson;
+import org.onap.msb.sdclient.wrapper.consul.util.ObjectMapperContextResolver;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.guava.GuavaModule;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.net.HostAndPort;
+
+/**
+ * Client for interacting with the Consul HTTP API.
+ *
+ * @author rfast
+ */
+public class Consul {
+
+ /**
+ * Default Consul HTTP API host.
+ */
+ public static final String DEFAULT_HTTP_HOST = "localhost";
+
+ /**
+ * Default Consul HTTP API port.
+ */
+ public static final int DEFAULT_HTTP_PORT = 8500;
+
+
+
+
+
+ private final HealthClient healthClient;
+
+
+ /**
+ * Private constructor.
+ *
+ * @param url The full URL of a running Consul instance.
+ * @param builder JAX-RS client builder instance.
+ */
+ private Consul(String url, ClientBuilder builder, ObjectMapper mapper) {
+
+ if (!FluentIterable.from(builder.getConfiguration().getClasses())
+ .filter(new Predicate<Class<?>>() {
+ @Override
+ public boolean apply(final Class<?> clazz) {
+ return JacksonJaxbJsonProvider.class.isAssignableFrom(clazz);
+ }
+ }).first().isPresent()) {
+ builder.register(JacksonJaxbJsonProvider.class);
+ }
+ final Client client = builder
+ .register(new ObjectMapperContextResolver(mapper))
+ .build();
+
+
+ this.healthClient = new HealthClient(client.target(url).path("v1").path("health"));
+
+
+
+// agentClient.ping();
+ }
+
+ /**
+ * Creates a new client given a complete URL.
+ *
+ * @deprecated Use {@link Consul.Builder}
+ *
+ * @param url The Consul API URL.
+ * @param builder The JAX-RS client builder instance.
+ * @return A new client.
+ */
+ @Deprecated
+ public static Consul newClient(String url, ClientBuilder builder, ObjectMapper mapper) {
+ return new Consul(url, builder, mapper);
+ }
+
+ /**
+ * Creates a new client given a host and a port.
+ *
+ * @deprecated Use {@link Consul.Builder}
+ *
+ * @param host The Consul API hostname or IP.
+ * @param port The Consul port.
+ * @param builder The JAX-RS client builder instance.
+ * @return A new client.
+ */
+ @Deprecated
+ public static Consul newClient(String host, int port, ClientBuilder builder, ObjectMapper mapper) {
+ try {
+ return new Consul(new URL("http", host, port, "").toString(), builder, mapper);
+ } catch (MalformedURLException e) {
+ throw new ConsulException("Bad Consul URL", e);
+ }
+ }
+
+ /**
+ * Creates a new client given a host and a port.
+ *
+ * @deprecated Use {@link Consul.Builder}
+ *
+ * @param host The Consul API hostname or IP.
+ * @param port The Consul port.
+ * @return A new client.
+ */
+ @Deprecated
+ public static Consul newClient(String host, int port) {
+ return newClient(host, port, ClientBuilder.newBuilder(), Jackson.MAPPER);
+ }
+
+ /**
+ * Creates a new client given a host and a port.
+ *
+ * @deprecated Use {@link Consul.Builder}
+ *
+ * @return A new client.
+ */
+ @Deprecated
+ public static Consul newClient() {
+ return newClient(DEFAULT_HTTP_HOST, DEFAULT_HTTP_PORT);
+ }
+
+
+
+ public HealthClient healthClient() {
+ return healthClient;
+ }
+ /**
+ * Creates a new {@link Builder} object.
+ *
+ * @return A new Consul builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder for {@link Consul} client objects.
+ */
+ public static class Builder {
+ private URL url;
+ private Optional<SSLContext> sslContext = Optional.absent();
+ private ObjectMapper objectMapper = Jackson.MAPPER;
+ private ClientBuilder clientBuilder = ClientBuilder.newBuilder();
+
+ {
+ try {
+ url = new URL("http", "localhost", 8500, "");
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Constructs a new builder.
+ */
+ Builder() {
+
+ }
+
+ /**
+ * Sets the URL from a {@link URL} object.
+ *
+ * @param url The Consul agent URL.
+ * @return The builder.
+ */
+ public Builder withUrl(URL url) {
+ this.url = url;
+
+ return this;
+ }
+
+ /**
+ * Sets the URL from a {@link HostAndPort} object.
+ *
+ * @param hostAndPort The Consul agent host and port.
+ * @return The builder.
+ */
+ public Builder withHostAndPort(HostAndPort hostAndPort) {
+ try {
+ this.url = new URL("http", hostAndPort.getHostText(), hostAndPort.getPort(), "");
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the URL from a string.
+ *
+ * @param url The Consul agent URL.
+ * @return The builder.
+ */
+ public Builder withUrl(String url) {
+ try {
+ this.url = new URL(url);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the {@link SSLContext} for the client.
+ *
+ * @param sslContext The SSL context for HTTPS agents.
+ * @return The builder.
+ */
+ public Builder withSslContext(SSLContext sslContext) {
+ this.sslContext = Optional.of(sslContext);
+
+ return this;
+ }
+
+ /**
+ * Sets the {@link ObjectMapper} for the client.
+ *
+ * @param objectMapper The {@link ObjectMapper} to use.
+ * @return The builder.
+ */
+ public Builder withObjectMapper(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+
+ objectMapper.registerModule(new GuavaModule());
+
+ return this;
+ }
+
+ /**
+ * Sets the JAX-RS {@link ClientBuilder} to use.
+ *
+ * @param clientBuilder The JAX-RS builder.
+ * @return This builder.
+ */
+ public Builder withClientBuilder(ClientBuilder clientBuilder) {
+ this.clientBuilder = clientBuilder;
+
+ return this;
+ }
+
+ /**
+ * Constructs a new {@link Consul} client.
+ *
+ * @return A new Consul client.
+ */
+ public Consul build() {
+ if (this.sslContext.isPresent()) {
+ this.clientBuilder.sslContext(this.sslContext.get());
+ }
+
+ return new Consul(this.url.toExternalForm(), this.clientBuilder, this.objectMapper);
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java
new file mode 100644
index 0000000..b76aa38
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul;
+
+/**
+ * Wraps an exception thrown whilst interacting with the Consul API.
+ */
+public class ConsulException extends RuntimeException {
+
+ /**
+ * Constructs an instance of this class.
+ *
+ * @param message The exception message.
+ */
+ public ConsulException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an instance of this class.
+ *
+ * @param message The exception message.
+ * @param throwable The wrapped {@link java.lang.Throwable} object.
+ */
+ public ConsulException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java
new file mode 100644
index 0000000..61f7cbd
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java
@@ -0,0 +1,246 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul;
+
+import static org.onap.msb.sdclient.wrapper.consul.util.ClientUtil.response;
+
+import java.util.List;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.GenericType;
+
+import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback;
+import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse;
+import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth;
+import org.onap.msb.sdclient.wrapper.consul.option.CatalogOptions;
+import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions;
+
+/**
+ * HTTP Client for /v1/health/ endpoints.
+ */
+public class HealthClient {
+
+
+ private static final GenericType<List<ServiceHealth>> TYPE_SERVICE_HEALTH_LIST =
+ new GenericType<List<ServiceHealth>>() {};
+
+ private final WebTarget webTarget;
+
+ /**
+ * Constructs an instance of this class.
+ *
+ * @param webTarget The {@link javax.ws.rs.client.WebTarget} to base requests from.
+ */
+ HealthClient(WebTarget webTarget) {
+ this.webTarget = webTarget;
+ }
+
+
+
+ /**
+ * Retrieves the healthchecks for all healthy service instances.
+ *
+ * GET /v1/health/service/{service}?passing
+ *
+ * @param service The service to query.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service) {
+ return getHealthyServiceInstances(service, null, QueryOptions.BLANK);
+ }
+
+ /**
+ * Retrieves the healthchecks for all healthy service instances in a given datacenter.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}&amp;passing
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, CatalogOptions catalogOptions) {
+ return getHealthyServiceInstances(service, catalogOptions, QueryOptions.BLANK);
+ }
+
+ /**
+ * Retrieves the healthchecks for all healthy service instances with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?passing
+ *
+ * @param service The service to query.
+ * @param queryOptions The Query Options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, QueryOptions queryOptions) {
+ return getHealthyServiceInstances(service, null, queryOptions);
+ }
+
+ /**
+ * Retrieves the healthchecks for all healthy service instances in a given datacenter with
+ * {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}&amp;passing
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, CatalogOptions catalogOptions,
+ QueryOptions queryOptions) {
+ return response(webTarget.path("service").path(service).queryParam("passing", "true"),
+ catalogOptions, queryOptions, TYPE_SERVICE_HEALTH_LIST);
+ }
+
+ /**
+ * Asynchronously retrieves the healthchecks for all healthy service instances in a given
+ * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}&amp;passing
+ *
+ * Experimental.
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @param callback Callback implemented by callee to handle results.
+ */
+ public void getHealthyServiceInstances(String service, CatalogOptions catalogOptions,
+ QueryOptions queryOptions,
+ ConsulResponseCallback<List<ServiceHealth>> callback) {
+ response(webTarget.path("service").path(service).queryParam("passing", "true"),
+ catalogOptions, queryOptions, TYPE_SERVICE_HEALTH_LIST, callback);
+ }
+
+ /**
+ * Asynchronously retrieves the healthchecks for all healthy service instances in a given
+ * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}&amp;passing
+ *
+ * Experimental.
+ *
+ * @param service The service to query.
+ * @param queryOptions The Query Options to use.
+ * @param callback Callback implemented by callee to handle results.
+ */
+ public void getHealthyServiceInstances(String service, QueryOptions queryOptions,
+ ConsulResponseCallback<List<ServiceHealth>> callback) {
+ response(webTarget.path("service").path(service).queryParam("passing", "true"),
+ CatalogOptions.BLANK, queryOptions, TYPE_SERVICE_HEALTH_LIST, callback);
+ }
+
+ /**
+ * Retrieves the healthchecks for all nodes.
+ *
+ * GET /v1/health/service/{service}
+ *
+ * @param service The service to query.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service) {
+ return getAllServiceInstances(service, null, QueryOptions.BLANK);
+ }
+
+ /**
+ * Retrieves the healthchecks for all nodes in a given datacenter.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, CatalogOptions catalogOptions) {
+ return getAllServiceInstances(service, catalogOptions, QueryOptions.BLANK);
+ }
+
+ /**
+ * Retrieves the healthchecks for all nodes with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}
+ *
+ * @param service The service to query.
+ * @param queryOptions The Query Options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, QueryOptions queryOptions) {
+ return getAllServiceInstances(service, null, queryOptions);
+ }
+
+ /**
+ * Retrieves the healthchecks for all nodes in a given datacenter with
+ * {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of
+ * {@link com.orbitz.consul.model.health.HealthCheck} objects.
+ */
+ public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, CatalogOptions catalogOptions,
+ QueryOptions queryOptions) {
+ return response(webTarget.path("service").path(service), catalogOptions, queryOptions,
+ TYPE_SERVICE_HEALTH_LIST);
+ }
+
+ /**
+ * Asynchronously retrieves the healthchecks for all nodes in a given
+ * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}
+ *
+ * Experimental.
+ *
+ * @param service The service to query.
+ * @param catalogOptions The catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @param callback Callback implemented by callee to handle results.
+ */
+ public void getAllServiceInstances(String service, CatalogOptions catalogOptions,
+ QueryOptions queryOptions,
+ ConsulResponseCallback<List<ServiceHealth>> callback) {
+ response(webTarget.path("service").path(service), catalogOptions, queryOptions,
+ TYPE_SERVICE_HEALTH_LIST, callback);
+ }
+
+ /**
+ * Asynchronously retrieves the healthchecks for all nodes in a given
+ * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}.
+ *
+ * GET /v1/health/service/{service}?dc={datacenter}
+ *
+ * Experimental.
+ *
+ * @param service The service to query.
+ * @param queryOptions The Query Options to use.
+ * @param callback Callback implemented by callee to handle results.
+ */
+ public void getAllServiceInstances(String service, QueryOptions queryOptions,
+ ConsulResponseCallback<List<ServiceHealth>> callback) {
+ response(webTarget.path("service").path(service), CatalogOptions.BLANK,
+ queryOptions, TYPE_SERVICE_HEALTH_LIST, callback);
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java
new file mode 100644
index 0000000..33fcb48
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.async;
+
+import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse;
+
+/**
+ * For API calls that support long-polling, this callback is used to handle
+ * the result on success or failure for an async HTTP call.
+ *
+ * @param <T> The Response type.
+ */
+public interface ConsulResponseCallback<T> {
+
+ /**
+ * Callback for a successful {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse}.
+ *
+ * @param consulResponse The Consul response.
+ */
+ void onComplete(ConsulResponse<T> consulResponse);
+
+ /**
+ * Callback for an unsuccessful request.
+ *
+ * @param throwable The exception thrown.
+ */
+ void onFailure(Throwable throwable);
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java
new file mode 100644
index 0000000..60e4a0a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java
@@ -0,0 +1,229 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.cache;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+
+import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback;
+import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse;
+import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * A cache structure that can provide an up-to-date read-only
+ * map backed by consul data
+ *
+ * @param <V>
+ */
+public class ConsulCache<K, V> {
+
+ enum State {latent, starting, started, stopped }
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(ConsulCache.class);
+
+ private final AtomicReference<BigInteger> latestIndex = new AtomicReference<BigInteger>(null);
+ private final AtomicReference<ImmutableMap<K, V>> lastResponse = new AtomicReference<ImmutableMap<K, V>>(ImmutableMap.<K, V>of());
+ private final AtomicReference<State> state = new AtomicReference<State>(State.latent);
+ private final CountDownLatch initLatch = new CountDownLatch(1);
+ private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+ private final CopyOnWriteArrayList<Listener<K, V>> listeners = new CopyOnWriteArrayList<Listener<K, V>>();
+
+ private final Function<V, K> keyConversion;
+ private final CallbackConsumer<V> callBackConsumer;
+ private final ConsulResponseCallback<List<V>> responseCallback;
+
+ ConsulCache(
+ Function<V, K> keyConversion,
+ CallbackConsumer<V> callbackConsumer) {
+ this(keyConversion, callbackConsumer, 10, TimeUnit.SECONDS);
+ }
+
+ ConsulCache(
+ Function<V, K> keyConversion,
+ CallbackConsumer<V> callbackConsumer,
+ final long backoffDelayQty,
+ final TimeUnit backoffDelayUnit) {
+
+ this.keyConversion = keyConversion;
+ this.callBackConsumer = callbackConsumer;
+
+ this.responseCallback = new ConsulResponseCallback<List<V>>() {
+ @Override
+ public void onComplete(ConsulResponse<List<V>> consulResponse) {
+
+ if (!isRunning()) {
+ return;
+ }
+ updateIndex(consulResponse);
+ ImmutableMap<K, V> full = convertToMap(consulResponse);
+
+ boolean changed = !full.equals(lastResponse.get());
+// LOGGER.info("node changed:"+changed+"----"+full);
+ if (changed) {
+ // changes
+ lastResponse.set(full);
+ }
+
+ if (changed) {
+ for (Listener<K, V> l : listeners) {
+ l.notify(full);
+ }
+ }
+
+ if (state.compareAndSet(State.starting, State.started)) {
+ initLatch.countDown();
+ }
+ runCallback();
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+
+ if (!isRunning()) {
+ return;
+ }
+ LOGGER.error(String.format("Error getting response from consul. will retry in %d %s", backoffDelayQty, backoffDelayUnit), throwable);
+
+ executorService.schedule(new Runnable() {
+ @Override
+ public void run() {
+ runCallback();
+ }
+ }, backoffDelayQty, backoffDelayUnit);
+ }
+ };
+ }
+
+ public void start() throws Exception {
+ checkState(state.compareAndSet(State.latent, State.starting),"Cannot transition from state %s to %s", state.get(), State.starting);
+ runCallback();
+ }
+
+ public void stop() throws Exception {
+ State previous = state.getAndSet(State.stopped);
+ if (previous != State.stopped) {
+ executorService.shutdownNow();
+ }
+ }
+
+ private void runCallback() {
+ if (isRunning()) {
+ callBackConsumer.consume(latestIndex.get(), responseCallback);
+ }
+ }
+
+ private boolean isRunning() {
+ return state.get() == State.started || state.get() == State.starting;
+ }
+
+ public boolean awaitInitialized(long timeout, TimeUnit unit) throws InterruptedException {
+ return initLatch.await(timeout, unit);
+ }
+
+ public ImmutableMap<K, V> getMap() {
+ return lastResponse.get();
+ }
+
+ @VisibleForTesting
+ ImmutableMap<K, V> convertToMap(final ConsulResponse<List<V>> response) {
+ if (response == null || response.getResponse() == null || response.getResponse().isEmpty()) {
+ return ImmutableMap.of();
+ }
+
+ final ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
+ final Set<K> keySet = new HashSet<>();
+ for (final V v : response.getResponse()) {
+ final K key = keyConversion.apply(v);
+ if (key != null) {
+ if (!keySet.contains(key)) {
+ builder.put(key, v);
+ } else {
+ System.out.println(key.toString());
+ LOGGER.warn("Duplicate service encountered. May differ by tags. Try using more specific tags? " + key.toString());
+ }
+ }
+ keySet.add(key);
+ }
+ return builder.build();
+ }
+
+ private void updateIndex(ConsulResponse<List<V>> consulResponse) {
+ if (consulResponse != null && consulResponse.getIndex() != null) {
+ this.latestIndex.set(consulResponse.getIndex());
+ }
+ }
+
+ protected static QueryOptions watchParams(BigInteger index, int blockSeconds) {
+ if (index == null) {
+ return QueryOptions.BLANK;
+ } else {
+ return QueryOptions.blockSeconds(blockSeconds, index).build();
+ }
+ }
+
+ /**
+ * passed in by creators to vary the content of the cached values
+ *
+ * @param <V>
+ */
+ protected interface CallbackConsumer<V> {
+ void consume(BigInteger index, ConsulResponseCallback<List<V>> callback);
+ }
+
+ /**
+ * Implementers can register a listener to receive
+ * a new map when it changes
+ *
+ * @param <V>
+ */
+ public interface Listener<K, V> {
+ void notify(Map<K, V> newValues);
+ }
+
+ public boolean addListener(Listener<K, V> listener) {
+ boolean added = listeners.add(listener);
+ if (state.get() == State.started) {
+ listener.notify(lastResponse.get());
+ }
+ return added;
+ }
+
+ public boolean removeListener(Listener<K, V> listener) {
+ return listeners.remove(listener);
+ }
+
+ @VisibleForTesting
+ protected State getState() {
+ return state.get();
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java
new file mode 100644
index 0000000..3a60cee
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.cache;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.onap.msb.sdclient.wrapper.consul.HealthClient;
+import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback;
+import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth;
+
+import com.google.common.base.Function;
+
+public class HealthCache extends ConsulCache<String, ServiceHealth>{
+
+ private final String serviceName;
+
+ private HealthCache(Function<ServiceHealth, String> keyConversion,
+ ConsulCache.CallbackConsumer<ServiceHealth> callbackConsumer,String serviceName) {
+ super(keyConversion, callbackConsumer);
+ this.serviceName=serviceName;
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public static HealthCache newCache(
+ final HealthClient healthClient,
+ final String serviceName,
+ final int watchSeconds){
+ Function<ServiceHealth,String> keyExtractor = new Function<ServiceHealth, String>() {
+ @Override
+ public String apply(ServiceHealth input) {
+ //return input.getKey().substring(rootPath.length() + 1);
+ return input.getService().getId();
+ }
+ };
+
+ final CallbackConsumer<ServiceHealth> callbackConsumer = new CallbackConsumer<ServiceHealth>() {
+ @Override
+ public void consume(BigInteger index, ConsulResponseCallback<List<ServiceHealth>> callback) {
+ healthClient.getHealthyServiceInstances(serviceName, watchParams(index, watchSeconds),callback);
+ }
+ };
+
+
+ return new HealthCache(keyExtractor, callbackConsumer,serviceName);
+
+
+ }
+
+ public String getServiceName(){
+ return this.serviceName;
+ }
+
+
+} \ No newline at end of file
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java
new file mode 100644
index 0000000..7a704e5
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model;
+
+import com.google.common.base.Objects;
+
+import java.math.BigInteger;
+
+public class ConsulResponse<T> {
+
+ private final T response;
+ private final long lastContact;
+ private final boolean knownLeader;
+ private final BigInteger index;
+
+ public ConsulResponse(T response, long lastContact, boolean knownLeader, BigInteger index) {
+ this.response = response;
+ this.lastContact = lastContact;
+ this.knownLeader = knownLeader;
+ this.index = index;
+ }
+
+ public T getResponse() {
+ return response;
+ }
+
+ public long getLastContact() {
+ return lastContact;
+ }
+
+ public boolean isKnownLeader() {
+ return knownLeader;
+ }
+
+ public BigInteger getIndex() {
+ return index;
+ }
+
+ @Override
+ public String toString() {
+ return "ConsulResponse{" +
+ "response=" + response +
+ ", lastContact=" + lastContact +
+ ", knownLeader=" + knownLeader +
+ ", index=" + index +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ConsulResponse that = (ConsulResponse) o;
+
+ return Objects.equal(this.response, that.response) &&
+ Objects.equal(this.lastContact, that.lastContact) &&
+ Objects.equal(this.knownLeader, that.knownLeader) &&
+ Objects.equal(this.index, that.index);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(response, lastContact, knownLeader, index);
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java
new file mode 100644
index 0000000..c40c8cf
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java
@@ -0,0 +1,265 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model.health;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import java.util.List;
+import javax.annotation.Generated;
+
+/**
+ * Immutable implementation of {@link Node}.
+ * <p>
+ * Use the builder to create immutable instances:
+ * {@code ImmutableNode.builder()}.
+ */
+@SuppressWarnings("all")
+@Generated({"Immutables.generator", "Node"})
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class ImmutableNode extends Node {
+ private final String node;
+ private final String address;
+
+ private ImmutableNode(String node, String address) {
+ this.node = node;
+ this.address = address;
+ }
+
+ /**
+ * @return The value of the {@code node} attribute
+ */
+ @JsonProperty(value = "Node")
+ @Override
+ public String getNode() {
+ return node;
+ }
+
+ /**
+ * @return The value of the {@code address} attribute
+ */
+ @JsonProperty(value = "Address")
+ @Override
+ public String getAddress() {
+ return address;
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Node#getNode() node} attribute.
+ * An equals check used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for node
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableNode withNode(String value) {
+ if (this.node.equals(value)) return this;
+ return new ImmutableNode(Preconditions.checkNotNull(value, "node"), this.address);
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Node#getAddress() address} attribute.
+ * An equals check used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for address
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableNode withAddress(String value) {
+ if (this.address.equals(value)) return this;
+ return new ImmutableNode(this.node, Preconditions.checkNotNull(value, "address"));
+ }
+
+ /**
+ * This instance is equal to all instances of {@code ImmutableNode} that have equal attribute values.
+ * @return {@code true} if {@code this} is equal to {@code another} instance
+ */
+ @Override
+ public boolean equals(Object another) {
+ if (this == another) return true;
+ return another instanceof ImmutableNode
+ && equalTo((ImmutableNode) another);
+ }
+
+ private boolean equalTo(ImmutableNode another) {
+ return node.equals(another.node)
+ && address.equals(another.address);
+ }
+
+ /**
+ * Computes a hash code from attributes: {@code node}, {@code address}.
+ * @return hashCode value
+ */
+ @Override
+ public int hashCode() {
+ int h = 31;
+ h = h * 17 + node.hashCode();
+ h = h * 17 + address.hashCode();
+ return h;
+ }
+
+ /**
+ * Prints the immutable value {@code Node...} with all non-generated
+ * and non-auxiliary attribute values.
+ * @return A string representation of the value
+ */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper("Node")
+ .add("node", node)
+ .add("address", address)
+ .toString();
+ }
+
+ /**
+ * Utility type used to correctly read immutable object from JSON representation.
+ * @deprecated Do not use this type directly, it exists only for the <em>Jackson</em>-binding infrastructure
+ */
+ @Deprecated
+ @JsonDeserialize
+ static final class Json extends Node {
+ String node;
+ String address;
+ @JsonProperty(value = "Node")
+ public void setNode(String node) {
+ this.node = node;
+ }
+ @JsonProperty(value = "Address")
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ @Override
+ public String getNode() { throw new UnsupportedOperationException(); }
+ @Override
+ public String getAddress() { throw new UnsupportedOperationException(); }
+ }
+
+ /**
+ * @param json A JSON-bindable data structure
+ * @return An immutable value type
+ * @deprecated Do not use this method directly, it exists only for the <em>Jackson</em>-binding infrastructure
+ */
+ @Deprecated
+ @JsonCreator
+ static ImmutableNode fromJson(Json json) {
+ ImmutableNode.Builder builder = ImmutableNode.builder();
+ if (json.node != null) {
+ builder.node(json.node);
+ }
+ if (json.address != null) {
+ builder.address(json.address);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Creates an immutable copy of a {@link Node} value.
+ * Uses accessors to get values to initialize the new immutable instance.
+ * If an instance is already immutable, it is returned as is.
+ * @param instance The instance to copy
+ * @return A copied immutable Node instance
+ */
+ public static ImmutableNode copyOf(Node instance) {
+ if (instance instanceof ImmutableNode) {
+ return (ImmutableNode) instance;
+ }
+ return ImmutableNode.builder()
+ .from(instance)
+ .build();
+ }
+
+ /**
+ * Creates a builder for {@link ImmutableNode ImmutableNode}.
+ * @return A new ImmutableNode builder
+ */
+ public static ImmutableNode.Builder builder() {
+ return new ImmutableNode.Builder();
+ }
+
+ /**
+ * Builds instances of type {@link ImmutableNode ImmutableNode}.
+ * Initialize attributes and then invoke the {@link #build()} method to create an
+ * immutable instance.
+ * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection,
+ * but instead used immediately to create instances.</em>
+ */
+ public static final class Builder {
+ private static final long INIT_BIT_NODE = 0x1L;
+ private static final long INIT_BIT_ADDRESS = 0x2L;
+ private long initBits = 0x3;
+
+ private String node;
+ private String address;
+
+ private Builder() {
+ }
+
+ /**
+ * Fill a builder with attribute values from the provided {@code Node} instance.
+ * Regular attribute values will be replaced with those from the given instance.
+ * Absent optional values will not replace present values.
+ * @param instance The instance from which to copy values
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder from(Node instance) {
+ Preconditions.checkNotNull(instance, "instance");
+ node(instance.getNode());
+ address(instance.getAddress());
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Node#getNode() node} attribute.
+ * @param node The value for node
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder node(String node) {
+ this.node = Preconditions.checkNotNull(node, "node");
+ initBits &= ~INIT_BIT_NODE;
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Node#getAddress() address} attribute.
+ * @param address The value for address
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder address(String address) {
+ this.address = Preconditions.checkNotNull(address, "address");
+ initBits &= ~INIT_BIT_ADDRESS;
+ return this;
+ }
+
+ /**
+ * Builds a new {@link ImmutableNode ImmutableNode}.
+ * @return An immutable instance of Node
+ * @throws java.lang.IllegalStateException if any required attributes are missing
+ */
+ public ImmutableNode build() throws IllegalStateException {
+ if (initBits != 0) {
+ throw new IllegalStateException(formatRequiredAttributesMessage());
+ }
+ return new ImmutableNode(node, address);
+ }
+
+ private String formatRequiredAttributesMessage() {
+ List<String> attributes = Lists.newArrayList();
+ if ((initBits & INIT_BIT_NODE) != 0) attributes.add("node");
+ if ((initBits & INIT_BIT_ADDRESS) != 0) attributes.add("address");
+ return "Cannot build Node, some of required attributes are not set " + attributes;
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java
new file mode 100644
index 0000000..20da538
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java
@@ -0,0 +1,477 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model.health;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import java.util.List;
+import javax.annotation.Generated;
+
+/**
+ * Immutable implementation of {@link Service}.
+ * <p>
+ * Use the builder to create immutable instances:
+ * {@code ImmutableService.builder()}.
+ */
+@SuppressWarnings("all")
+@Generated({"Immutables.generator", "Service"})
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class ImmutableService extends Service {
+ private final String id;
+ private final String service;
+ private final ImmutableList<String> tags;
+ private final String address;
+ private final int port;
+
+ private ImmutableService(
+ String id,
+ String service,
+ ImmutableList<String> tags,
+ String address,
+ int port) {
+ this.id = id;
+ this.service = service;
+ this.tags = tags;
+ this.address = address;
+ this.port = port;
+ }
+
+ /**
+ * @return The value of the {@code id} attribute
+ */
+ @JsonProperty(value = "ID")
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @return The value of the {@code service} attribute
+ */
+ @JsonProperty(value = "Service")
+ @Override
+ public String getService() {
+ return service;
+ }
+
+ /**
+ * @return The value of the {@code tags} attribute
+ */
+ @JsonProperty(value = "Tags")
+ @JsonDeserialize(as = ImmutableList.class, contentAs = String.class)
+ @Override
+ public ImmutableList<String> getTags() {
+ return tags;
+ }
+
+ /**
+ * @return The value of the {@code address} attribute
+ */
+ @JsonProperty(value = "Address")
+ @Override
+ public String getAddress() {
+ return address;
+ }
+
+ /**
+ * @return The value of the {@code port} attribute
+ */
+ @JsonProperty(value = "Port")
+ @Override
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Service#getId() id} attribute.
+ * An equals check used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for id
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableService withId(String value) {
+ if (this.id.equals(value)) return this;
+ return new ImmutableService(
+ Preconditions.checkNotNull(value, "id"),
+ this.service,
+ this.tags,
+ this.address,
+ this.port);
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Service#getService() service} attribute.
+ * An equals check used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for service
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableService withService(String value) {
+ if (this.service.equals(value)) return this;
+ return new ImmutableService(
+ this.id,
+ Preconditions.checkNotNull(value, "service"),
+ this.tags,
+ this.address,
+ this.port);
+ }
+
+ /**
+ * Copy the current immutable object with elements that replace the content of {@link Service#getTags() tags}.
+ * @param elements The elements to set
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableService withTags(String... elements) {
+ ImmutableList<String> newValue = ImmutableList.copyOf(elements);
+ return new ImmutableService(this.id, this.service, newValue, this.address, this.port);
+ }
+
+ /**
+ * Copy the current immutable object with elements that replace the content of {@link Service#getTags() tags}.
+ * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}.
+ * @param elements An iterable of tags elements to set
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableService withTags(Iterable<String> elements) {
+ if (this.tags == elements) return this;
+ ImmutableList<String> newValue = ImmutableList.copyOf(elements);
+ return new ImmutableService(this.id, this.service, newValue, this.address, this.port);
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Service#getAddress() address} attribute.
+ * An equals check used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for address
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableService withAddress(String value) {
+ if (this.address.equals(value)) return this;
+ return new ImmutableService(
+ this.id,
+ this.service,
+ this.tags,
+ Preconditions.checkNotNull(value, "address"),
+ this.port);
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link Service#getPort() port} attribute.
+ * A value equality check is used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for port
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableService withPort(int value) {
+ if (this.port == value) return this;
+ return new ImmutableService(this.id, this.service, this.tags, this.address, value);
+ }
+
+ /**
+ * This instance is equal to all instances of {@code ImmutableService} that have equal attribute values.
+ * @return {@code true} if {@code this} is equal to {@code another} instance
+ */
+ @Override
+ public boolean equals(Object another) {
+ if (this == another) return true;
+ return another instanceof ImmutableService
+ && equalTo((ImmutableService) another);
+ }
+
+ private boolean equalTo(ImmutableService another) {
+ return id.equals(another.id)
+ && service.equals(another.service)
+ && tags.equals(another.tags)
+ && address.equals(another.address)
+ && port == another.port;
+ }
+
+ /**
+ * Computes a hash code from attributes: {@code id}, {@code service}, {@code tags}, {@code address}, {@code port}.
+ * @return hashCode value
+ */
+ @Override
+ public int hashCode() {
+ int h = 31;
+ h = h * 17 + id.hashCode();
+ h = h * 17 + service.hashCode();
+ h = h * 17 + tags.hashCode();
+ h = h * 17 + address.hashCode();
+ h = h * 17 + port;
+ return h;
+ }
+
+ /**
+ * Prints the immutable value {@code Service...} with all non-generated
+ * and non-auxiliary attribute values.
+ * @return A string representation of the value
+ */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper("Service")
+ .add("id", id)
+ .add("service", service)
+ .add("tags", tags)
+ .add("address", address)
+ .add("port", port)
+ .toString();
+ }
+
+ /**
+ * Utility type used to correctly read immutable object from JSON representation.
+ * @deprecated Do not use this type directly, it exists only for the <em>Jackson</em>-binding infrastructure
+ */
+ @Deprecated
+ @JsonDeserialize
+ static final class Json extends Service {
+ String id;
+ String service;
+ List<String> tags = ImmutableList.of();
+ String address;
+ Integer port;
+ @JsonProperty(value = "ID")
+ public void setId(String id) {
+ this.id = id;
+ }
+ @JsonProperty(value = "Service")
+ public void setService(String service) {
+ this.service = service;
+ }
+ @JsonProperty(value = "Tags")
+ @JsonDeserialize(as = ImmutableList.class, contentAs = String.class)
+ public void setTags(List<String> tags) {
+ this.tags = tags;
+ }
+ @JsonProperty(value = "Address")
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ @JsonProperty(value = "Port")
+ public void setPort(int port) {
+ this.port = port;
+ }
+ @Override
+ public String getId() { throw new UnsupportedOperationException(); }
+ @Override
+ public String getService() { throw new UnsupportedOperationException(); }
+ @Override
+ public List<String> getTags() { throw new UnsupportedOperationException(); }
+ @Override
+ public String getAddress() { throw new UnsupportedOperationException(); }
+ @Override
+ public int getPort() { throw new UnsupportedOperationException(); }
+ }
+
+ /**
+ * @param json A JSON-bindable data structure
+ * @return An immutable value type
+ * @deprecated Do not use this method directly, it exists only for the <em>Jackson</em>-binding infrastructure
+ */
+ @Deprecated
+ @JsonCreator
+ static ImmutableService fromJson(Json json) {
+ ImmutableService.Builder builder = ImmutableService.builder();
+ if (json.id != null) {
+ builder.id(json.id);
+ }
+ if (json.service != null) {
+ builder.service(json.service);
+ }
+ if (json.tags != null) {
+ builder.addAllTags(json.tags);
+ }
+ if (json.address != null) {
+ builder.address(json.address);
+ }
+ if (json.port != null) {
+ builder.port(json.port);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Creates an immutable copy of a {@link Service} value.
+ * Uses accessors to get values to initialize the new immutable instance.
+ * If an instance is already immutable, it is returned as is.
+ * @param instance The instance to copy
+ * @return A copied immutable Service instance
+ */
+ public static ImmutableService copyOf(Service instance) {
+ if (instance instanceof ImmutableService) {
+ return (ImmutableService) instance;
+ }
+ return ImmutableService.builder()
+ .from(instance)
+ .build();
+ }
+
+ /**
+ * Creates a builder for {@link ImmutableService ImmutableService}.
+ * @return A new ImmutableService builder
+ */
+ public static ImmutableService.Builder builder() {
+ return new ImmutableService.Builder();
+ }
+
+ /**
+ * Builds instances of type {@link ImmutableService ImmutableService}.
+ * Initialize attributes and then invoke the {@link #build()} method to create an
+ * immutable instance.
+ * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection,
+ * but instead used immediately to create instances.</em>
+ */
+ public static final class Builder {
+ private static final long INIT_BIT_ID = 0x1L;
+ private static final long INIT_BIT_SERVICE = 0x2L;
+ private static final long INIT_BIT_ADDRESS = 0x4L;
+ private static final long INIT_BIT_PORT = 0x8L;
+ private long initBits = 0xf;
+
+ private String id;
+ private String service;
+ private ImmutableList.Builder<String> tagsBuilder = ImmutableList.builder();
+ private String address;
+ private int port;
+
+ private Builder() {
+ }
+
+ /**
+ * Fill a builder with attribute values from the provided {@code Service} instance.
+ * Regular attribute values will be replaced with those from the given instance.
+ * Absent optional values will not replace present values.
+ * Collection elements and entries will be added, not replaced.
+ * @param instance The instance from which to copy values
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder from(Service instance) {
+ Preconditions.checkNotNull(instance, "instance");
+ id(instance.getId());
+ service(instance.getService());
+ addAllTags(instance.getTags());
+ address(instance.getAddress());
+ port(instance.getPort());
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Service#getId() id} attribute.
+ * @param id The value for id
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder id(String id) {
+ this.id = Preconditions.checkNotNull(id, "id");
+ initBits &= ~INIT_BIT_ID;
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Service#getService() service} attribute.
+ * @param service The value for service
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder service(String service) {
+ this.service = Preconditions.checkNotNull(service, "service");
+ initBits &= ~INIT_BIT_SERVICE;
+ return this;
+ }
+
+ /**
+ * Adds one element to {@link Service#getTags() tags} list.
+ * @param element A tags element
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder addTags(String element) {
+ tagsBuilder.add(element);
+ return this;
+ }
+
+ /**
+ * Adds elements to {@link Service#getTags() tags} list.
+ * @param elements An array of tags elements
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder addTags(String... elements) {
+ tagsBuilder.add(elements);
+ return this;
+ }
+
+ /**
+ * Sets or replaces all elements for {@link Service#getTags() tags} list.
+ * @param elements An iterable of tags elements
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder tags(Iterable<String> elements) {
+ tagsBuilder = ImmutableList.builder();
+ return addAllTags(elements);
+ }
+
+ /**
+ * Adds elements to {@link Service#getTags() tags} list.
+ * @param elements An iterable of tags elements
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder addAllTags(Iterable<String> elements) {
+ tagsBuilder.addAll(elements);
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Service#getAddress() address} attribute.
+ * @param address The value for address
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder address(String address) {
+ this.address = Preconditions.checkNotNull(address, "address");
+ initBits &= ~INIT_BIT_ADDRESS;
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link Service#getPort() port} attribute.
+ * @param port The value for port
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder port(int port) {
+ this.port = port;
+ initBits &= ~INIT_BIT_PORT;
+ return this;
+ }
+
+ /**
+ * Builds a new {@link ImmutableService ImmutableService}.
+ * @return An immutable instance of Service
+ * @throws java.lang.IllegalStateException if any required attributes are missing
+ */
+ public ImmutableService build() throws IllegalStateException {
+ if (initBits != 0) {
+ throw new IllegalStateException(formatRequiredAttributesMessage());
+ }
+ return new ImmutableService(id, service, tagsBuilder.build(), address, port);
+ }
+
+ private String formatRequiredAttributesMessage() {
+ List<String> attributes = Lists.newArrayList();
+ if ((initBits & INIT_BIT_ID) != 0) attributes.add("id");
+ if ((initBits & INIT_BIT_SERVICE) != 0) attributes.add("service");
+ if ((initBits & INIT_BIT_ADDRESS) != 0) attributes.add("address");
+ if ((initBits & INIT_BIT_PORT) != 0) attributes.add("port");
+ return "Cannot build Service, some of required attributes are not set " + attributes;
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java
new file mode 100644
index 0000000..839dc46
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model.health;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+
+@JsonSerialize(as = ImmutableNode.class)
+@JsonDeserialize(as = ImmutableNode.class)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public abstract class Node {
+
+ @JsonProperty("Node")
+ public abstract String getNode();
+
+ @JsonProperty("Address")
+ public abstract String getAddress();
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java
new file mode 100644
index 0000000..0cb04ea
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model.health;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.collect.ImmutableList;
+
+
+@JsonSerialize(as = ImmutableService.class)
+@JsonDeserialize(as = ImmutableService.class)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public abstract class Service {
+
+ @JsonProperty("ID")
+ public abstract String getId();
+
+ @JsonProperty("Service")
+ public abstract String getService();
+
+ @JsonProperty("Tags")
+ @JsonDeserialize(as = ImmutableList.class, contentAs = String.class)
+ public abstract List<String> getTags();
+
+ @JsonProperty("Address")
+ public abstract String getAddress();
+
+ @JsonProperty("Port")
+ public abstract int getPort();
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java
new file mode 100644
index 0000000..91f3c7d
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.model.health;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Objects;
+
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ServiceHealth {
+
+ @JsonProperty("Node")
+ public Node node;
+
+ @JsonProperty("Service")
+ public Service service;
+
+ public Node getNode() {
+ return node;
+ }
+
+ public void setNode(Node node) {
+ this.node = node;
+ }
+
+ public Service getService() {
+ return service;
+ }
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(this == other)
+ return true;
+ if(other instanceof ServiceHealth)
+ {
+ ServiceHealth that = (ServiceHealth)other;
+ return Objects.equal(node, that.node) && Objects.equal(service, that.service);
+ } else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(node, service);
+ }
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java
new file mode 100644
index 0000000..e608c0f
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import static org.onap.msb.sdclient.wrapper.consul.option.Options.optionallyAdd;
+
+import javax.ws.rs.client.WebTarget;
+
+import com.google.common.base.Optional;
+
+
+public abstract class CatalogOptions implements ParamAdder {
+
+ public abstract Optional<String> getDatacenter();
+ public abstract Optional<String> getTag();
+
+ public static final CatalogOptions BLANK = ImmutableCatalogOptions.builder().build();
+
+ @Override
+ public final WebTarget apply(final WebTarget input) {
+ WebTarget added = optionallyAdd(input, "dc", getDatacenter());
+ added = optionallyAdd(added, "tag", getTag());
+ return added;
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java
new file mode 100644
index 0000000..b60fa0b
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+public enum ConsistencyMode {
+ DEFAULT, STALE, CONSISTENT
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java
new file mode 100644
index 0000000..2a87f8a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java
@@ -0,0 +1,250 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import javax.annotation.Generated;
+
+/**
+ * Immutable implementation of {@link CatalogOptions}.
+ * <p>
+ * Use the builder to create immutable instances:
+ * {@code ImmutableCatalogOptions.builder()}.
+ */
+@SuppressWarnings("all")
+@Generated({"Immutables.generator", "CatalogOptions"})
+public final class ImmutableCatalogOptions extends CatalogOptions {
+ private final Optional<String> datacenter;
+ private final Optional<String> tag;
+
+ private ImmutableCatalogOptions(
+ Optional<String> datacenter,
+ Optional<String> tag) {
+ this.datacenter = datacenter;
+ this.tag = tag;
+ }
+
+ /**
+ * @return The value of the {@code datacenter} attribute
+ */
+ @Override
+ public Optional<String> getDatacenter() {
+ return datacenter;
+ }
+
+ /**
+ * @return The value of the {@code tag} attribute
+ */
+ @Override
+ public Optional<String> getTag() {
+ return tag;
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link CatalogOptions#getDatacenter() datacenter} attribute.
+ * @param value The value for datacenter
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableCatalogOptions withDatacenter(String value) {
+ Optional<String> newValue = Optional.of(value);
+ return new ImmutableCatalogOptions(newValue, this.tag);
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link CatalogOptions#getDatacenter() datacenter} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for datacenter
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableCatalogOptions withDatacenter(Optional<String> optional) {
+ Optional<String> value = Preconditions.checkNotNull(optional, "datacenter");
+ if (this.datacenter == value) return this;
+ return new ImmutableCatalogOptions(value, this.tag);
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link CatalogOptions#getTag() tag} attribute.
+ * @param value The value for tag
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableCatalogOptions withTag(String value) {
+ Optional<String> newValue = Optional.of(value);
+ return new ImmutableCatalogOptions(this.datacenter, newValue);
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link CatalogOptions#getTag() tag} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for tag
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableCatalogOptions withTag(Optional<String> optional) {
+ Optional<String> value = Preconditions.checkNotNull(optional, "tag");
+ if (this.tag == value) return this;
+ return new ImmutableCatalogOptions(this.datacenter, value);
+ }
+
+ /**
+ * This instance is equal to all instances of {@code ImmutableCatalogOptions} that have equal attribute values.
+ * @return {@code true} if {@code this} is equal to {@code another} instance
+ */
+ @Override
+ public boolean equals(Object another) {
+ if (this == another) return true;
+ return another instanceof ImmutableCatalogOptions
+ && equalTo((ImmutableCatalogOptions) another);
+ }
+
+ private boolean equalTo(ImmutableCatalogOptions another) {
+ return datacenter.equals(another.datacenter)
+ && tag.equals(another.tag);
+ }
+
+ /**
+ * Computes a hash code from attributes: {@code datacenter}, {@code tag}.
+ * @return hashCode value
+ */
+ @Override
+ public int hashCode() {
+ int h = 31;
+ h = h * 17 + datacenter.hashCode();
+ h = h * 17 + tag.hashCode();
+ return h;
+ }
+
+ /**
+ * Prints the immutable value {@code CatalogOptions...} with all non-generated
+ * and non-auxiliary attribute values.
+ * @return A string representation of the value
+ */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper("CatalogOptions")
+ .add("datacenter", datacenter)
+ .add("tag", tag)
+ .toString();
+ }
+
+ /**
+ * Creates an immutable copy of a {@link CatalogOptions} value.
+ * Uses accessors to get values to initialize the new immutable instance.
+ * If an instance is already immutable, it is returned as is.
+ * @param instance The instance to copy
+ * @return A copied immutable CatalogOptions instance
+ */
+ public static ImmutableCatalogOptions copyOf(CatalogOptions instance) {
+ if (instance instanceof ImmutableCatalogOptions) {
+ return (ImmutableCatalogOptions) instance;
+ }
+ return ImmutableCatalogOptions.builder()
+ .from(instance)
+ .build();
+ }
+
+ /**
+ * Creates a builder for {@link ImmutableCatalogOptions ImmutableCatalogOptions}.
+ * @return A new ImmutableCatalogOptions builder
+ */
+ public static ImmutableCatalogOptions.Builder builder() {
+ return new ImmutableCatalogOptions.Builder();
+ }
+
+ /**
+ * Builds instances of type {@link ImmutableCatalogOptions ImmutableCatalogOptions}.
+ * Initialize attributes and then invoke the {@link #build()} method to create an
+ * immutable instance.
+ * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection,
+ * but instead used immediately to create instances.</em>
+ */
+ public static final class Builder {
+ private Optional<String> datacenter = Optional.absent();
+ private Optional<String> tag = Optional.absent();
+
+ private Builder() {
+ }
+
+ /**
+ * Fill a builder with attribute values from the provided {@code CatalogOptions} instance.
+ * Regular attribute values will be replaced with those from the given instance.
+ * Absent optional values will not replace present values.
+ * @param instance The instance from which to copy values
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder from(CatalogOptions instance) {
+ Preconditions.checkNotNull(instance, "instance");
+ Optional<String> datacenterOptional = instance.getDatacenter();
+ if (datacenterOptional.isPresent()) {
+ datacenter(datacenterOptional);
+ }
+ Optional<String> tagOptional = instance.getTag();
+ if (tagOptional.isPresent()) {
+ tag(tagOptional);
+ }
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link CatalogOptions#getDatacenter() datacenter} to datacenter.
+ * @param datacenter The value for datacenter
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder datacenter(String datacenter) {
+ this.datacenter = Optional.of(datacenter);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link CatalogOptions#getDatacenter() datacenter} to datacenter.
+ * @param datacenter The value for datacenter
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder datacenter(Optional<String> datacenter) {
+ this.datacenter = Preconditions.checkNotNull(datacenter, "datacenter");
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link CatalogOptions#getTag() tag} to tag.
+ * @param tag The value for tag
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder tag(String tag) {
+ this.tag = Optional.of(tag);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link CatalogOptions#getTag() tag} to tag.
+ * @param tag The value for tag
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder tag(Optional<String> tag) {
+ this.tag = Preconditions.checkNotNull(tag, "tag");
+ return this;
+ }
+
+ /**
+ * Builds a new {@link ImmutableCatalogOptions ImmutableCatalogOptions}.
+ * @return An immutable instance of CatalogOptions
+ * @throws java.lang.IllegalStateException if any required attributes are missing
+ */
+ public ImmutableCatalogOptions build() throws IllegalStateException {
+ return new ImmutableCatalogOptions(datacenter, tag);
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java
new file mode 100644
index 0000000..6c4db6b
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java
@@ -0,0 +1,530 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Booleans;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import javax.annotation.Generated;
+
+/**
+ * Immutable implementation of {@link QueryOptions}.
+ * <p>
+ * Use the builder to create immutable instances:
+ * {@code ImmutableQueryOptions.builder()}.
+ */
+@SuppressWarnings("all")
+@Generated({"Immutables.generator", "QueryOptions"})
+public final class ImmutableQueryOptions extends QueryOptions {
+ private final Optional<String> wait;
+ private final Optional<String> token;
+ private final Optional<BigInteger> index;
+ private final Optional<String> near;
+ private final ConsistencyMode consistencyMode;
+ private final boolean isBlocking;
+ private final boolean hasToken;
+
+ private ImmutableQueryOptions(ImmutableQueryOptions.Builder builder) {
+ this.wait = builder.wait;
+ this.token = builder.token;
+ this.index = builder.index;
+ this.near = builder.near;
+ if (builder.consistencyMode != null) {
+ initShim.consistencyMode(builder.consistencyMode);
+ }
+ this.consistencyMode = initShim.getConsistencyMode();
+ this.isBlocking = initShim.isBlocking();
+ this.hasToken = initShim.hasToken();
+ this.initShim = null;
+ }
+
+ private ImmutableQueryOptions(
+ Optional<String> wait,
+ Optional<String> token,
+ Optional<BigInteger> index,
+ Optional<String> near,
+ ConsistencyMode consistencyMode) {
+ this.wait = wait;
+ this.token = token;
+ this.index = index;
+ this.near = near;
+ this.consistencyMode = consistencyMode;
+ initShim.consistencyMode(consistencyMode);
+ this.isBlocking = initShim.isBlocking();
+ this.hasToken = initShim.hasToken();
+ this.initShim = null;
+ }
+
+ private static final int STAGE_INITIALIZING = -1;
+ private static final int STAGE_UNINITIALIZED = 0;
+ private static final int STAGE_INITIALIZED = 1;
+ private volatile InitShim initShim = new InitShim();
+
+ private final class InitShim {
+ private ConsistencyMode consistencyMode;
+ private byte consistencyModeStage;
+
+ ConsistencyMode getConsistencyMode() {
+ if (consistencyModeStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage());
+ if (consistencyModeStage == STAGE_UNINITIALIZED) {
+ consistencyModeStage = STAGE_INITIALIZING;
+ this.consistencyMode = Preconditions.checkNotNull(ImmutableQueryOptions.super.getConsistencyMode(), "consistencyMode");
+ consistencyModeStage = STAGE_INITIALIZED;
+ }
+ return consistencyMode;
+ }
+
+ ConsistencyMode consistencyMode(ConsistencyMode value) {
+ this.consistencyMode = value;
+ consistencyModeStage = STAGE_INITIALIZED;
+ return value;
+ }
+ private boolean isBlocking;
+ private byte isBlockingStage;
+
+ boolean isBlocking() {
+ if (isBlockingStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage());
+ if (isBlockingStage == STAGE_UNINITIALIZED) {
+ isBlockingStage = STAGE_INITIALIZING;
+ this.isBlocking = ImmutableQueryOptions.super.isBlocking();
+ isBlockingStage = STAGE_INITIALIZED;
+ }
+ return isBlocking;
+ }
+ private boolean hasToken;
+ private byte hasTokenStage;
+
+ boolean hasToken() {
+ if (hasTokenStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage());
+ if (hasTokenStage == STAGE_UNINITIALIZED) {
+ hasTokenStage = STAGE_INITIALIZING;
+ this.hasToken = ImmutableQueryOptions.super.hasToken();
+ hasTokenStage = STAGE_INITIALIZED;
+ }
+ return hasToken;
+ }
+
+ private String formatInitCycleMessage() {
+ ArrayList<String> attributes = Lists.newArrayList();
+ if (consistencyModeStage == STAGE_INITIALIZING) attributes.add("consistencyMode");
+ if (isBlockingStage == STAGE_INITIALIZING) attributes.add("isBlocking");
+ if (hasTokenStage == STAGE_INITIALIZING) attributes.add("hasToken");
+ return "Cannot build QueryOptions, attribute initializers form cycle" + attributes;
+ }
+ }
+
+ /**
+ * @return The value of the {@code wait} attribute
+ */
+ @Override
+ public Optional<String> getWait() {
+ return wait;
+ }
+
+ /**
+ * @return The value of the {@code token} attribute
+ */
+ @Override
+ public Optional<String> getToken() {
+ return token;
+ }
+
+ /**
+ * @return The value of the {@code index} attribute
+ */
+ @Override
+ public Optional<BigInteger> getIndex() {
+ return index;
+ }
+
+ /**
+ * @return The value of the {@code near} attribute
+ */
+ @Override
+ public Optional<String> getNear() {
+ return near;
+ }
+
+ /**
+ * @return The value of the {@code consistencyMode} attribute
+ */
+ @Override
+ public ConsistencyMode getConsistencyMode() {
+ return initShim != null
+ ? initShim.getConsistencyMode()
+ : consistencyMode;
+ }
+
+ /**
+ * @return The computed-at-construction value of the {@code isBlocking} attribute
+ */
+ @Override
+ public boolean isBlocking() {
+ return initShim != null
+ ? initShim.isBlocking()
+ : isBlocking;
+ }
+
+ /**
+ * @return The computed-at-construction value of the {@code hasToken} attribute
+ */
+ @Override
+ public boolean hasToken() {
+ return initShim != null
+ ? initShim.hasToken()
+ : hasToken;
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getWait() wait} attribute.
+ * @param value The value for wait
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withWait(String value) {
+ Optional<String> newValue = Optional.of(value);
+ return validate(new ImmutableQueryOptions(newValue, this.token, this.index, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getWait() wait} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for wait
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withWait(Optional<String> optional) {
+ Optional<String> value = Preconditions.checkNotNull(optional, "wait");
+ if (this.wait == value) return this;
+ return validate(new ImmutableQueryOptions(value, this.token, this.index, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getToken() token} attribute.
+ * @param value The value for token
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withToken(String value) {
+ Optional<String> newValue = Optional.of(value);
+ return validate(new ImmutableQueryOptions(this.wait, newValue, this.index, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getToken() token} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for token
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withToken(Optional<String> optional) {
+ Optional<String> value = Preconditions.checkNotNull(optional, "token");
+ if (this.token == value) return this;
+ return validate(new ImmutableQueryOptions(this.wait, value, this.index, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getIndex() index} attribute.
+ * @param value The value for index
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withIndex(BigInteger value) {
+ Optional<BigInteger> newValue = Optional.of(value);
+ return validate(new ImmutableQueryOptions(this.wait, this.token, newValue, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getIndex() index} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for index
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withIndex(Optional<BigInteger> optional) {
+ Optional<BigInteger> value = Preconditions.checkNotNull(optional, "index");
+ if (this.index == value) return this;
+ return validate(new ImmutableQueryOptions(this.wait, this.token, value, this.near, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getNear() near} attribute.
+ * @param value The value for near
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withNear(String value) {
+ Optional<String> newValue = Optional.of(value);
+ return validate(new ImmutableQueryOptions(this.wait, this.token, this.index, newValue, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getNear() near} attribute.
+ * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}.
+ * @param optional A value for near
+ * @return A modified copy of {@code this} object
+ */
+ public final ImmutableQueryOptions withNear(Optional<String> optional) {
+ Optional<String> value = Preconditions.checkNotNull(optional, "near");
+ if (this.near == value) return this;
+ return validate(new ImmutableQueryOptions(this.wait, this.token, this.index, value, this.consistencyMode));
+ }
+
+ /**
+ * Copy the current immutable object by setting a value for the {@link QueryOptions#getConsistencyMode() consistencyMode} attribute.
+ * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}.
+ * @param value A new value for consistencyMode
+ * @return A modified copy of the {@code this} object
+ */
+ public final ImmutableQueryOptions withConsistencyMode(ConsistencyMode value) {
+ if (this.consistencyMode == value) return this;
+ return validate(new ImmutableQueryOptions(
+ this.wait,
+ this.token,
+ this.index,
+ this.near,
+ Preconditions.checkNotNull(value, "consistencyMode")));
+ }
+
+ /**
+ * This instance is equal to all instances of {@code ImmutableQueryOptions} that have equal attribute values.
+ * @return {@code true} if {@code this} is equal to {@code another} instance
+ */
+ @Override
+ public boolean equals(Object another) {
+ if (this == another) return true;
+ return another instanceof ImmutableQueryOptions
+ && equalTo((ImmutableQueryOptions) another);
+ }
+
+ private boolean equalTo(ImmutableQueryOptions another) {
+ return wait.equals(another.wait)
+ && token.equals(another.token)
+ && index.equals(another.index)
+ && near.equals(another.near)
+ && consistencyMode.equals(another.consistencyMode)
+ && isBlocking == another.isBlocking
+ && hasToken == another.hasToken;
+ }
+
+ /**
+ * Computes a hash code from attributes: {@code wait}, {@code token}, {@code index}, {@code near}, {@code consistencyMode}, {@code isBlocking}, {@code hasToken}.
+ * @return hashCode value
+ */
+ @Override
+ public int hashCode() {
+ int h = 31;
+ h = h * 17 + wait.hashCode();
+ h = h * 17 + token.hashCode();
+ h = h * 17 + index.hashCode();
+ h = h * 17 + near.hashCode();
+ h = h * 17 + consistencyMode.hashCode();
+ h = h * 17 + Booleans.hashCode(isBlocking);
+ h = h * 17 + Booleans.hashCode(hasToken);
+ return h;
+ }
+
+ /**
+ * Prints the immutable value {@code QueryOptions...} with all non-generated
+ * and non-auxiliary attribute values.
+ * @return A string representation of the value
+ */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper("QueryOptions")
+ .add("wait", wait)
+ .add("token", token)
+ .add("index", index)
+ .add("near", near)
+ .add("consistencyMode", consistencyMode)
+ .add("isBlocking", isBlocking)
+ .add("hasToken", hasToken)
+ .toString();
+ }
+
+ private static ImmutableQueryOptions validate(ImmutableQueryOptions instance) {
+ instance.validate();
+ return instance;
+ }
+
+ /**
+ * Creates an immutable copy of a {@link QueryOptions} value.
+ * Uses accessors to get values to initialize the new immutable instance.
+ * If an instance is already immutable, it is returned as is.
+ * @param instance The instance to copy
+ * @return A copied immutable QueryOptions instance
+ */
+ public static ImmutableQueryOptions copyOf(QueryOptions instance) {
+ if (instance instanceof ImmutableQueryOptions) {
+ return (ImmutableQueryOptions) instance;
+ }
+ return ImmutableQueryOptions.builder()
+ .from(instance)
+ .build();
+ }
+
+ /**
+ * Creates a builder for {@link ImmutableQueryOptions ImmutableQueryOptions}.
+ * @return A new ImmutableQueryOptions builder
+ */
+ public static ImmutableQueryOptions.Builder builder() {
+ return new ImmutableQueryOptions.Builder();
+ }
+
+ /**
+ * Builds instances of type {@link ImmutableQueryOptions ImmutableQueryOptions}.
+ * Initialize attributes and then invoke the {@link #build()} method to create an
+ * immutable instance.
+ * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection,
+ * but instead used immediately to create instances.</em>
+ */
+ public static final class Builder {
+ private Optional<String> wait = Optional.absent();
+ private Optional<String> token = Optional.absent();
+ private Optional<BigInteger> index = Optional.absent();
+ private Optional<String> near = Optional.absent();
+ private ConsistencyMode consistencyMode;
+
+ private Builder() {
+ }
+
+ /**
+ * Fill a builder with attribute values from the provided {@code QueryOptions} instance.
+ * Regular attribute values will be replaced with those from the given instance.
+ * Absent optional values will not replace present values.
+ * @param instance The instance from which to copy values
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder from(QueryOptions instance) {
+ Preconditions.checkNotNull(instance, "instance");
+ Optional<String> waitOptional = instance.getWait();
+ if (waitOptional.isPresent()) {
+ wait(waitOptional);
+ }
+ Optional<String> tokenOptional = instance.getToken();
+ if (tokenOptional.isPresent()) {
+ token(tokenOptional);
+ }
+ Optional<BigInteger> indexOptional = instance.getIndex();
+ if (indexOptional.isPresent()) {
+ index(indexOptional);
+ }
+ Optional<String> nearOptional = instance.getNear();
+ if (nearOptional.isPresent()) {
+ near(nearOptional);
+ }
+ consistencyMode(instance.getConsistencyMode());
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getWait() wait} to wait.
+ * @param wait The value for wait
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder wait(String wait) {
+ this.wait = Optional.of(wait);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getWait() wait} to wait.
+ * @param wait The value for wait
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder wait(Optional<String> wait) {
+ this.wait = Preconditions.checkNotNull(wait, "wait");
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getToken() token} to token.
+ * @param token The value for token
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder token(String token) {
+ this.token = Optional.of(token);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getToken() token} to token.
+ * @param token The value for token
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder token(Optional<String> token) {
+ this.token = Preconditions.checkNotNull(token, "token");
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getIndex() index} to index.
+ * @param index The value for index
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder index(BigInteger index) {
+ this.index = Optional.of(index);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getIndex() index} to index.
+ * @param index The value for index
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder index(Optional<BigInteger> index) {
+ this.index = Preconditions.checkNotNull(index, "index");
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getNear() near} to near.
+ * @param near The value for near
+ * @return {@code this} builder for chained invocation
+ */
+ public final Builder near(String near) {
+ this.near = Optional.of(near);
+ return this;
+ }
+
+ /**
+ * Initializes the optional value {@link QueryOptions#getNear() near} to near.
+ * @param near The value for near
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder near(Optional<String> near) {
+ this.near = Preconditions.checkNotNull(near, "near");
+ return this;
+ }
+
+ /**
+ * Initializes the value for the {@link QueryOptions#getConsistencyMode() consistencyMode} attribute.
+ * <p><em>If not set, this attribute will have a default value as returned by the initializer of {@link QueryOptions#getConsistencyMode() consistencyMode}.</em>
+ * @param consistencyMode The value for consistencyMode
+ * @return {@code this} builder for use in a chained invocation
+ */
+ public final Builder consistencyMode(ConsistencyMode consistencyMode) {
+ this.consistencyMode = Preconditions.checkNotNull(consistencyMode, "consistencyMode");
+ return this;
+ }
+
+ /**
+ * Builds a new {@link ImmutableQueryOptions ImmutableQueryOptions}.
+ * @return An immutable instance of QueryOptions
+ * @throws java.lang.IllegalStateException if any required attributes are missing
+ */
+ public ImmutableQueryOptions build() throws IllegalStateException {
+ return ImmutableQueryOptions.validate(new ImmutableQueryOptions(this));
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java
new file mode 100644
index 0000000..5d412df
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import com.google.common.base.Optional;
+
+import javax.ws.rs.client.WebTarget;
+
+public class Options {
+ private Options(){};
+
+ static <T> WebTarget optionallyAdd(WebTarget input, String key, Optional<T> val) {
+ return val.isPresent() ? input.queryParam(key, val.get()) : input;
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java
new file mode 100644
index 0000000..e5f6d44
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import com.google.common.base.Function;
+
+import javax.ws.rs.client.WebTarget;
+
+public interface ParamAdder extends Function<WebTarget, WebTarget> {}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java
new file mode 100644
index 0000000..3a09b82
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.option;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onap.msb.sdclient.wrapper.consul.option.Options.optionallyAdd;
+
+import java.math.BigInteger;
+
+import javax.ws.rs.client.WebTarget;
+
+import com.google.common.base.Optional;
+
+/**
+ * Container for common query options used by the Consul API.
+ */
+
+public abstract class QueryOptions implements ParamAdder {
+
+ public static final QueryOptions BLANK = ImmutableQueryOptions.builder().build();
+
+ public abstract Optional<String> getWait();
+ public abstract Optional<String> getToken();
+ public abstract Optional<BigInteger> getIndex();
+ public abstract Optional<String> getNear();
+
+
+ public ConsistencyMode getConsistencyMode() {
+ return ConsistencyMode.DEFAULT;
+ }
+
+
+ public boolean isBlocking() {
+ return getWait().isPresent();
+ }
+
+
+ public boolean hasToken() {
+ return getToken().isPresent();
+ }
+
+
+ void validate() {
+ if (isBlocking()) {
+ checkArgument(getIndex().isPresent(), "If wait is specified, index must also be specified");
+ }
+ }
+
+ public static ImmutableQueryOptions.Builder blockSeconds(int seconds, BigInteger index) {
+ return blockBuilder("s", seconds, index);
+ }
+
+ public static ImmutableQueryOptions.Builder blockMinutes(int minutes, BigInteger index) {
+ return blockBuilder("m", minutes, index);
+ }
+
+ private static ImmutableQueryOptions.Builder blockBuilder(String identifier, int qty, BigInteger index) {
+ return ImmutableQueryOptions.builder()
+ .wait(String.format("%s%s", qty, identifier))
+ .index(index);
+ }
+
+ @Override
+ public WebTarget apply(WebTarget input) {
+
+ WebTarget added = input;
+ switch (getConsistencyMode()) {
+ case CONSISTENT:
+ added = added.queryParam("consistent", "");
+ break;
+ case STALE:
+ added = added.queryParam("stale", "");
+ break;
+ }
+
+ if (isBlocking()) {
+ added = added.queryParam("wait", getWait().get())
+ .queryParam("index", String.valueOf(getIndex().get()));
+ }
+
+ added = optionallyAdd(added, "token", getToken());
+ added = optionallyAdd(added, "near", getToken());
+
+ return added;
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java
new file mode 100644
index 0000000..7e3b7a2
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java
@@ -0,0 +1,246 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.util;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import javax.ws.rs.ServerErrorException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.InvocationCallback;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onap.msb.sdclient.wrapper.consul.ConsulException;
+import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback;
+import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse;
+import org.onap.msb.sdclient.wrapper.consul.option.CatalogOptions;
+import org.onap.msb.sdclient.wrapper.consul.option.ParamAdder;
+import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A collection of stateless utility methods for use in constructing
+ * requests and responses to the Consul HTTP API.
+ */
+public class ClientUtil {
+
+ /**
+ * Applies all key/values from the params map to query string parameters.
+ *
+ * @param webTarget The JAX-RS target to apply the query parameters.
+ * @param params Map of parameters.
+ * @return The new target with the parameters applied.
+ */
+ public static WebTarget queryParams(WebTarget webTarget, Map<String, String> params) {
+ WebTarget target = webTarget;
+
+ if(params != null) {
+ for(Map.Entry<String, String> entry : params.entrySet()) {
+ target = target.queryParam(entry.getKey(), entry.getValue());
+ }
+ }
+
+ return target;
+ }
+
+ /**
+ * Given a {@link org.onap.msb.sdclient.wrapper.consul.option.ParamAdder} object, adds the
+ * appropriate query string parameters to the request being built.
+ *
+ * @param webTarget The base {@link javax.ws.rs.client.WebTarget}.
+ * @param paramAdder will add specific params to the target.
+ * @return A {@link javax.ws.rs.client.WebTarget} with all appropriate query
+ * string parameters.
+ */
+ public static WebTarget addParams(WebTarget webTarget, ParamAdder paramAdder) {
+ return paramAdder == null ? webTarget : paramAdder.apply(webTarget);
+ }
+
+ /**
+ * Generates a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} for a specific datacenter,
+ * set of {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}, and a result type.
+ *
+ * @param target The base {@link javax.ws.rs.client.WebTarget}.
+ * @param catalogOptions Catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @param type The generic type to marshall the resulting data to.
+ * @param <T> The result type.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse}.
+ */
+ public static <T> ConsulResponse<T> response(WebTarget target, CatalogOptions catalogOptions,
+ QueryOptions queryOptions,
+ GenericType<T> type) {
+ target = addParams(target, catalogOptions);
+ target = addParams(target, queryOptions);
+
+ return response(target, type);
+ }
+
+ /**
+ * Generates a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} for a specific datacenter,
+ * set of {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}, and a result type.
+ *
+ * @param target The base {@link javax.ws.rs.client.WebTarget}.
+ * @param catalogOptions Catalog specific options to use.
+ * @param queryOptions The Query Options to use.
+ * @param type The generic type to marshall the resulting data to.
+ * @param <T> The result type.
+ */
+ public static <T> void response(WebTarget target, CatalogOptions catalogOptions,
+ QueryOptions queryOptions,
+ GenericType<T> type,
+ ConsulResponseCallback<T> callback) {
+
+ target = addParams(target, catalogOptions);
+ target = addParams(target, queryOptions);
+
+ response(target, type, callback);
+ }
+
+ /**
+ * Given a {@link javax.ws.rs.client.WebTarget} object and a type to marshall
+ * the result JSON into, complete the HTTP GET request.
+ *
+ * @param webTarget The JAX-RS target.
+ * @param responseType The class to marshall the JSON into.
+ * @param <T> The class to marshall the JSON into.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing the result.
+ */
+ public static <T> ConsulResponse<T> response(WebTarget webTarget, GenericType<T> responseType) {
+ Response response = webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).get();
+
+ return consulResponse(responseType, response);
+ }
+
+ /**
+ * Given a {@link javax.ws.rs.client.WebTarget} object and a type to marshall
+ * the result JSON into, complete the HTTP GET request.
+ *
+ * @param webTarget The JAX-RS target.
+ * @param responseType The class to marshall the JSON into.
+ * @param callback The callback object to handle the result on a different thread.
+ * @param <T> The class to marshall the JSON into.
+ */
+ public static <T> void response(WebTarget webTarget, final GenericType<T> responseType,
+ final ConsulResponseCallback<T> callback) {
+ webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).async().get(new InvocationCallback<Response>() {
+
+ @Override
+ public void completed(Response response) {
+ try {
+ callback.onComplete(consulResponse(responseType, response));
+ } catch (Exception ex) {
+ callback.onFailure(ex);
+ }
+ }
+
+ @Override
+ public void failed(Throwable throwable) {
+ callback.onFailure(throwable);
+ }
+ });
+ }
+
+ /**
+ * Extracts Consul specific headers and adds them to a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse}
+ * object, which also contains the returned JSON entity.
+ *
+ * @param responseType The class to marshall the JSON to.
+ * @param response The HTTP response.
+ * @param <T> The class to marshall the JSON to.
+ * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} object.
+ */
+ private static <T> ConsulResponse<T> consulResponse(GenericType<T> responseType, Response response) {
+ handleErrors(response);
+
+ String indexHeaderValue = response.getHeaderString("X-Consul-Index");
+ String lastContactHeaderValue = response.getHeaderString("X-Consul-Lastcontact");
+ String knownLeaderHeaderValue = response.getHeaderString("X-Consul-Knownleader");
+
+ BigInteger index = new BigInteger(indexHeaderValue);
+ long lastContact = lastContactHeaderValue == null ? -1 : Long.parseLong(lastContactHeaderValue);
+ boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean.valueOf(knownLeaderHeaderValue);
+
+ ConsulResponse<T> consulResponse = new ConsulResponse<T>(readResponse(response, responseType), lastContact, knownLeader, index);
+
+ response.close();
+
+ return consulResponse;
+ }
+
+ /**
+ * Converts a {@link Response} object to the generic type provided, or an empty
+ * representation if appropriate
+ *
+ * @param response response
+ * @param responseType response type
+ * @param <T>
+ * @return the re
+ */
+ @SuppressWarnings("unchecked")
+ private static <T> T readResponse(Response response, GenericType<T> responseType) {
+ if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
+ // would be nice I knew a better way to do this
+ if (responseType.getRawType() == List.class) {
+ return (T) ImmutableList.of();
+ } else if (responseType.getRawType() == Optional.class) {
+ return (T) Optional.absent();
+ } else if(responseType.getRawType() == Map.class) {
+ return (T) ImmutableMap.of();
+ } else {
+ // Not sure if this case will be reached, but if it is it'll be nice to know
+ throw new IllegalStateException("Cannot determine empty representation for " + responseType.getRawType());
+ }
+ }
+ return response.readEntity(responseType);
+ }
+
+ /**
+ * Since Consul returns plain text when an error occurs, check for
+ * unsuccessful HTTP status code, and throw an exception with the text
+ * from Consul as the message.
+ *
+ * @param response The HTTP response.
+ */
+ public static void handleErrors(Response response) {
+
+ if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL
+ || response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
+ // not an error
+ return;
+ }
+
+ try {
+ final String message = response.hasEntity() ? response.readEntity(String.class) : null;
+ if (response.getStatusInfo().getFamily() == Response.Status.Family.SERVER_ERROR) {
+ throw new ServerErrorException(message, response);
+ } else {
+ throw new WebApplicationException(message, response);
+ }
+ } catch (Exception e) {
+ throw new ConsulException(e.getLocalizedMessage(), e);
+ } finally {
+ response.close();
+ }
+ }
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java
new file mode 100644
index 0000000..95af542
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.guava.GuavaModule;
+
+public class Jackson {
+
+ public static final ObjectMapper MAPPER = newObjectMapper();
+
+ private static ObjectMapper newObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.registerModule(new GuavaModule());
+ return mapper;
+ }
+
+ private Jackson() {}
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java
new file mode 100644
index 0000000..95247b5
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.consul.util;
+
+import javax.ws.rs.ext.ContextResolver;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
+
+ private final ObjectMapper objectMapper;
+ public ObjectMapperContextResolver(final ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public ObjectMapper getContext(final Class<?> type) {
+ return objectMapper;
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java
new file mode 100644
index 0000000..454a07a
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.sdclient.DiscoverAppConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @ClassName: ConfigUtil
+ * @Description: TODO(服务发现配置项工具类)
+ * @author tanghua10186366
+ * @date 2017年1月23日
+ *
+ */
+public class ConfigUtil {
+
+ private static ConfigUtil instance = new ConfigUtil();
+
+
+ private ConfigUtil() {}
+
+ public static ConfigUtil getInstance() {
+ return instance;
+ }
+
+
+ private String tcpudpPortRangeStart= DiscoverUtil.TCP_UDP_PORT_RANGE_START;
+
+ private String tcpudpPortRangeEnd=DiscoverUtil.TCP_UDP_PORT_RANGE_END;
+
+ private String consulAddress = DiscoverUtil.CONSUL_ADDRESSS;
+
+ private String consulRegisterMode=DiscoverUtil.CONSUL_REGISTER_MODE;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class);
+
+ public void initConsulClientInfo(DiscoverAppConfig config) {
+
+
+ String env_CONSUL_IP = System.getenv("CONSUL_IP");
+
+
+ if (StringUtils.isNotBlank(env_CONSUL_IP)) {
+ String consul_port = DiscoverUtil.CONSUL_DEFAULT_PORT;
+ try {
+ consul_port = config.getConsulAdderss().split(":")[1];
+ } catch (Exception e) {
+ LOGGER.error("initConsulClientInfo throw err:" + e.getMessage());
+ }
+
+ consulAddress = env_CONSUL_IP + ":" + consul_port;
+ } else if (StringUtils.isNotBlank(config.getConsulAdderss())) {
+ {
+ consulAddress = config.getConsulAdderss();
+ }
+
+
+ LOGGER.info("init Discover CONSUL ADDRESSS:" + consulAddress);
+
+
+ }
+ }
+
+ public void initTCP_UDP_portRange(){
+
+ String env_TCP_UDP_PORT_RANGE_START=System.getenv("TCP_UDP_PORT_RANGE_START");
+ String env_TCP_UDP_PORT_RANGE_END=System.getenv("TCP_UDP_PORT_RANGE_END");
+
+
+ if(StringUtils.isNotBlank(env_TCP_UDP_PORT_RANGE_START))
+ {
+ tcpudpPortRangeStart=env_TCP_UDP_PORT_RANGE_START;
+ }
+
+
+ if(StringUtils.isNotBlank(env_TCP_UDP_PORT_RANGE_END))
+ {
+ tcpudpPortRangeEnd=env_TCP_UDP_PORT_RANGE_END;
+ }
+
+ LOGGER.info("init TCP_UDP portRange:"+ tcpudpPortRangeStart+"-"+tcpudpPortRangeEnd);
+
+ }
+
+ public void initConsulRegisterMode(DiscoverAppConfig config){
+
+ String env_CONSUL_REGISTER_MODE=System.getenv("CONSUL_REGISTER_MODE");
+
+ if(StringUtils.isNotBlank(env_CONSUL_REGISTER_MODE))
+ {
+ consulRegisterMode=env_CONSUL_REGISTER_MODE;
+ }
+ else{
+ if(StringUtils.isNotBlank(config.getConsulRegisterMode())){
+ consulRegisterMode=config.getConsulRegisterMode();
+ }
+ }
+
+ LOGGER.info("init Consul Register Mode:"+consulRegisterMode);
+
+ }
+
+
+
+ public String getConsulAddress() {
+ return consulAddress;
+ }
+
+ public String getTcpudpPortRangeStart() {
+ return tcpudpPortRangeStart;
+ }
+
+
+ public String getTcpudpPortRangeEnd() {
+ return tcpudpPortRangeEnd;
+ }
+
+
+ public String getConsulRegisterMode() {
+ return consulRegisterMode;
+ }
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java
new file mode 100644
index 0000000..fb61294
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+* @ClassName: ApiRouteUtil
+* @Description: TODO(ApiRoute工具类)
+* @author tanghua10186366
+* @date 2015年9月29日 下午3:19:51
+*
+*/
+public class DiscoverUtil {
+
+
+ public static final String CONSUL_DEFAULT_PORT="8500";
+
+ public static final String APIGATEWAY_SERVINCE = "apigateway";
+
+ public static final String ROUTER_SERVINCE = "router";
+
+ public static final String APIGATEWAY_SERVINCE_ALL = "all";
+
+ public static final String APIGATEWAY_SERVINCE_DEFAULT = "default";
+
+ public static final String VISUAL_RANGE_IN = "1";
+
+ public static final String VISUAL_RANGE_OUT = "0";
+
+ public static final String SERVICENAME_LINE_NAMESPACE="-";
+
+ public static final String SPLIT_LINE="|";
+
+ public static final String EXTERNAL_NODE_NAME="externalService";
+
+
+ public static final String REQUEST_SUCCESS = "SUCCESS";
+
+ public static final String REQUEST_FAIL = "FAIL";
+
+ public static final String VISUAL_RANGE_LIST="0,1";
+
+ public static final String PROTOCOL_LIST="REST,HTTP,MQ,FTP,SNMP,UI,TCP,UDP,PORTAL";
+
+ public static final String LB_POLICY_LIST="round-robin,ip_hash,least_conn,client_custom";
+
+ public static final String LB_PARAMS_LIST="weight,max_fails,fail_timeout";
+
+ public static final String CHECK_TYPE_LIST="HTTP,TCP,TTL";
+
+ public static final String CHECK_HA_ROLE_LIST="active,standby";
+
+ public static final String CONSUL_CATALOG_URL="/v1/catalog";
+
+ public static final String CONSUL_AGENT_URL="/v1/agent/service";
+
+ public static final String CONSUL_AGENT_TTL_URL="/v1/agent/check/pass/";
+
+ public static final String CONSUL_HEALTH_URL="/v1/health/service/";
+
+ public static final String[] PUBLISH_PROTOCOL={"TCP","UDP","HTTP","REST","UI","PORTAL"};
+
+ public static final String[] HTTP_PROTOCOL={"HTTP","REST","UI","PORTAL"};
+
+ public static final String TCP_UDP_PORT_RANGE_START="28001";
+
+ public static final String TCP_UDP_PORT_RANGE_END="30000";
+
+ public static final String CONSUL_ADDRESSS="127.0.0.1:8500";
+
+ public static final String CONSUL_REGISTER_MODE="catalog";
+
+// public static boolean isProtocol_tcp_udp(String protocol){
+// return "TCP".equals(protocol) || "UDP".equals(protocol);
+// }
+//
+
+ public static String getRealIp(HttpServletRequest request) {
+ String ip = request.getHeader("X-Forwarded-For");
+ if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
+ // 多次反向代理后会有多个ip值,第一个ip才是真实ip
+ int index = ip.indexOf(",");
+ if (index != -1) {
+ return ip.substring(0, index);
+ } else {
+ return ip;
+ }
+ }
+ ip = request.getHeader("X-Real-IP");
+
+ if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
+ return ip;
+ }
+
+
+ return request.getRemoteAddr();
+
+ }
+
+ public static boolean checkVisualRangeIn(String visualRange){
+ return checkExist(visualRange,DiscoverUtil.VISUAL_RANGE_IN, "|");
+ }
+
+ public static boolean checkVisualRangeOut(String visualRange){
+ return checkExist(visualRange,DiscoverUtil.VISUAL_RANGE_OUT, "|");
+ }
+
+ public static boolean checkExist(String list,String value,String separator){
+ String[] listArray=StringUtils.split(list, separator);
+
+ for(int i=0;i<listArray.length;i++){
+ if(value.equals(listArray[i])) return true;
+ }
+ return false;
+ }
+
+ public static boolean checkExist(String[] list,String value){
+ for(int i=0;i<list.length;i++){
+ if(value.equals(list[i])) return true;
+ }
+ return false;
+ }
+
+ public static boolean contain(String[] array,String value[]){
+ for(int i=0;i<array.length;i++){
+ for(int n=0;n<value.length;n++){
+ if(array[i].equals(value[n])){
+ return true;
+ }
+ }
+ }
+ return false;
+
+ }
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java
new file mode 100644
index 0000000..7d06d15
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java
@@ -0,0 +1,218 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.util;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.onap.msb.sdclient.core.ConsulResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HttpClientUtil {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(HttpClientUtil.class);
+
+ public static int httpPostWithJSON(String url, String params) {
+ int result = 0;
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ HttpPost httpPost = new HttpPost(url);
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+ httpPost.setHeader("Accept", "application/json");
+ httpPost.setEntity(new StringEntity(params, Charset.forName("UTF-8")));
+ try {
+ CloseableHttpResponse res = httpClient.execute(httpPost);
+ result = res.getStatusLine().getStatusCode();
+ if (res.getStatusLine().getStatusCode() != 200) {
+ logger.error(String.valueOf(result));
+ }
+ res.close();
+ } catch (IOException e) {
+ String errorMsg = url + ":httpPostWithJSON connect faild";
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ String errorMsg = url + ":close httpClient faild";
+ }
+ }
+
+ return result;
+
+ }
+
+ public static void delete(String url, String parameter) throws Exception {
+ String result = null;
+ String baseUrl;
+ if (parameter != null) {
+ List<NameValuePair> params = new ArrayList<NameValuePair>();
+ params.add(new BasicNameValuePair("serviceName", parameter));
+ baseUrl = url + "?" + URLEncodedUtils.format(params, "UTF-8");
+ } else {
+ baseUrl = url;
+ }
+
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ ;
+ try {
+
+ HttpDelete httpDelete = new HttpDelete(baseUrl);
+ CloseableHttpResponse res = httpClient.execute(httpDelete);
+
+ if (res.getStatusLine().getStatusCode() != 200) {
+ throw new Exception("delete fail");
+ }
+
+ res.close();
+ } catch (IOException e) {
+ String errorMsg = baseUrl + ":delete connect faild";
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ String errorMsg = baseUrl + ":close httpClient faild";
+ }
+ }
+
+ }
+
+ public static String httpGet(String url) {
+ String result = null;
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.addHeader("Content-type", "application/json; charset=utf-8");
+ httpGet.setHeader("Accept", "application/json");
+ try {
+ CloseableHttpResponse res = httpClient.execute(httpGet);
+
+ res.getLastHeader("X-Consul-Index");
+ result = EntityUtils.toString(res.getEntity());
+ if (res.getStatusLine().getStatusCode() != 200) {
+ logger.error(result);
+ }
+ res.close();
+ } catch (ClientProtocolException e) {
+ String errorMsg = url + ":httpGetWithJSON connect faild";
+ logger.error(errorMsg);
+ } catch (IOException e) {
+ String errorMsg = url + ":httpGetWithJSON connect faild";
+ logger.error(errorMsg);
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ String errorMsg = url + ":close httpClient faild";
+ logger.error(errorMsg);
+ }
+ }
+
+ return result;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> ConsulResponse<T> httpWaitGet(String url) {
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.addHeader("Content-type", "application/json; charset=utf-8");
+ httpGet.setHeader("Accept", "application/json");
+ try {
+ CloseableHttpResponse res = httpClient.execute(httpGet);
+ String result = EntityUtils.toString(res.getEntity());
+
+ if (res.getStatusLine().getStatusCode() != 200) {
+ logger.error(result);
+ } else {
+ String indexHeaderValue = res.getLastHeader("X-Consul-Index")
+ .getValue();
+ BigInteger index = new BigInteger(indexHeaderValue);
+
+ return new ConsulResponse<T>((T) result, index);
+
+ }
+
+ res.close();
+ } catch (ClientProtocolException e) {
+ String errorMsg = url + ":httpGetWithJSON connect faild "
+ + e.getMessage();
+ logger.error(errorMsg);
+ } catch (IOException e) {
+ String errorMsg = url + ":httpGetWithJSON connect faild "
+ + e.getMessage();
+ logger.error(errorMsg);
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ String errorMsg = url + ":close httpClient faild "
+ + e.getMessage();
+ logger.error(errorMsg);
+ }
+ }
+
+ return null;
+
+ }
+
+ public static int httpGetStatus(String url) throws Exception {
+ int iStatus = 500;
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+
+ HttpGet httpGet = new HttpGet(url);
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setSocketTimeout(10000).setConnectTimeout(10000).build();// 设置请求和传输超时时间
+ httpGet.setConfig(requestConfig);
+ httpGet.addHeader("Content-type", "application/json; charset=utf-8");
+ httpGet.setHeader("Accept", "application/json");
+ try {
+ CloseableHttpResponse res = httpClient.execute(httpGet);
+
+ iStatus = res.getStatusLine().getStatusCode();
+ res.close();
+ } catch (ClientProtocolException e) {
+ logger.error(url + " httpGet connect faild:" + e.getMessage());
+ } catch (IOException e) {
+ logger.error(url + " httpGet connect faild:" + e.getMessage());
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ logger.error(url + " httpGet close faild:" + e.getMessage());
+ }
+ }
+
+ return iStatus;
+
+ }
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java
new file mode 100644
index 0000000..47eac9b
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java
@@ -0,0 +1,171 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.util;
+
+import java.util.List;
+import java.util.Map;
+
+import org.onap.msb.sdclient.core.CatalogService;
+import org.onap.msb.sdclient.core.HealthService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+
+public class JacksonJsonUtil {
+
+ private static final Logger logger = LoggerFactory.getLogger(JacksonJsonUtil.class);
+
+ private static ObjectMapper mapper;
+
+ /**
+ * 获取ObjectMapper实例
+ * @param createNew 方式:true,新实例;false,存在的mapper实例
+ * @return
+ */
+ public static synchronized ObjectMapper getMapperInstance() {
+ if (mapper == null) {
+ mapper = new ObjectMapper();
+ }
+ return mapper;
+ }
+
+ /**
+ * 将java对象转换成json字符串
+ * @param obj 准备转换的对象
+ * @return json字符串
+ * @throws Exception
+ */
+ public static String beanToJson(Object obj) throws Exception {
+ String json=null;
+ try {
+ ObjectMapper objectMapper = getMapperInstance();
+ objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ json =objectMapper.writeValueAsString(obj);
+ } catch (Exception e) {
+ logger.error("Class beanToJson faild:"+e.getMessage());
+ throw new Exception("Class beanToJson faild:"+e.getMessage());
+ }
+ return json;
+ }
+
+
+
+ /**
+ * 将json字符串转换成java对象
+ * @param json 准备转换的json字符串
+ * @param cls 准备转换的类
+ * @return
+ * @throws Exception
+ */
+ public static Object jsonToBean(String json, Class<?> cls) throws Exception {
+ Object vo =null;
+ try {
+ ObjectMapper objectMapper = getMapperInstance();
+ objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ vo = objectMapper.readValue(json, cls);
+
+ } catch (Exception e) {
+ logger.error(cls+" JsonTobean faild:"+e.getMessage());
+ throw new Exception(cls+" JsonTobean faild:"+e.getMessage());
+ }
+ return vo;
+ }
+
+
+
+
+ /**
+ * 将json字符串转换成java集合对象
+ * @param json 准备转换的json字符串
+ * @param cls 准备转换的类
+ * @return
+ * @throws Exception
+ */
+ public static List<CatalogService> jsonToListBean(String json) {
+ List<CatalogService> vo =null;
+ try {
+
+ ObjectMapper objectMapper = getMapperInstance();
+
+
+ vo = objectMapper.readValue(json, new TypeReference<List<CatalogService>>() {});
+
+ } catch (Exception e) {
+ String errorMsg =" JsonTobean faild:"+e.getMessage();
+ logger.error(errorMsg);
+ }
+ return vo;
+ }
+
+ public static <T> T jsonToListBean(String json,TypeReference<T> valueTypeRef) {
+ try {
+
+ ObjectMapper objectMapper = getMapperInstance();
+
+
+ return objectMapper.readValue(json, valueTypeRef);
+
+ } catch (Exception e) {
+ String errorMsg =" JsonTobean faild:"+e.getMessage();
+ logger.error(errorMsg);
+ }
+ return null;
+ }
+
+
+
+
+
+ /**
+ * 将json字符串转换成java集合对象
+ * @param json 准备转换的json字符串
+ * @param cls 准备转换的类
+ * @return
+ * @throws Exception
+ */
+ public static Map<String,String[]> jsonToMapBean(String json) {
+ Map<String,String[]> vo =null;
+ try {
+
+ ObjectMapper objectMapper = getMapperInstance();
+
+
+ vo = objectMapper.readValue(json, new TypeReference<Map<String,String[]>>() {});
+
+ } catch (Exception e) {
+ String errorMsg =" JsonTobean faild";
+ logger.error(errorMsg);
+ }
+ return vo;
+ }
+
+
+ public static void main(String[] args) {
+ String json="[{\"Node\":{\"Node\":\"A23179111\",\"Address\":\"10.74.44.27\",\"CreateIndex\":3,\"ModifyIndex\":318},\"Service\":{\"ID\":\"oo_10.74.56.36_5656\",\"Service\":\"oo\",\"Tags\":[\"url:/root\",\"protocol:REST\",\"version:\",\"visualRange:0|1\",\"ttl:-1\",\"status:1\",\"lb_policy:client_custom\",\"lb_server_params:weight=1 max_fails=1 fail_timeout=16s\",\"checkType:TCP\",\"checkInterval:10\",\"checkUrl:10.56.23.63:8989\"],\"Address\":\"10.74.56.36\",\"Port\":5656,\"EnableTagOverride\":false,\"CreateIndex\":314,\"ModifyIndex\":318},\"Checks\":[{\"Node\":\"A23179111\",\"CheckID\":\"serfHealth\",\"Name\":\"Serf Health Status\",\"Status\":\"passing\",\"Notes\":\"\",\"Output\":\"Agent alive and reachable\",\"ServiceID\":\"\",\"ServiceName\":\"\",\"CreateIndex\":3,\"ModifyIndex\":3},{\"Node\":\"A23179111\",\"CheckID\":\"service:oo_10.74.56.36_5656\",\"Name\":\"Service 'oo' check\",\"Status\":\"critical\",\"Notes\":\"\",\"Output\":\"\",\"ServiceID\":\"oo_10.74.56.36_5656\",\"ServiceName\":\"oo\",\"CreateIndex\":314,\"ModifyIndex\":318}]},{\"Node\":{\"Node\":\"A23179111\",\"Address\":\"10.74.44.27\",\"CreateIndex\":3,\"ModifyIndex\":318},\"Service\":{\"ID\":\"oo_10.78.36.36_111\",\"Service\":\"oo\",\"Tags\":[\"url:/root\",\"protocol:REST\",\"version:\",\"visualRange:0|1\",\"ttl:-1\",\"status:1\",\"lb_policy:client_custom\"],\"Address\":\"10.78.36.36\",\"Port\":111,\"EnableTagOverride\":false,\"CreateIndex\":315,\"ModifyIndex\":315},\"Checks\":[{\"Node\":\"A23179111\",\"CheckID\":\"serfHealth\",\"Name\":\"Serf Health Status\",\"Status\":\"passing\",\"Notes\":\"\",\"Output\":\"Agent alive and reachable\",\"ServiceID\":\"\",\"ServiceName\":\"\",\"CreateIndex\":3,\"ModifyIndex\":3}]}]";
+ List<HealthService> list=jsonToListBean(json,new TypeReference<List<HealthService>>() {
+ });
+ System.out.println(list);
+
+ }
+
+
+
+
+}
diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java
new file mode 100644
index 0000000..0203dee
--- /dev/null
+++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2016 ZTE, Inc. and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.msb.sdclient.wrapper.util;
+
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class RegExpTestUtil {
+
+ public static boolean httpUrlRegExpTest(String url){
+
+
+
+ String httpUrlReg = "^(|http:\\/\\/)(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)"
+ +":(\\d{1,5}).*$";
+ return Pattern.matches(httpUrlReg, url);
+
+}
+
+ public static boolean hostRegExpTest(String host){
+
+ String hostReg = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)"
+ +":(\\d{1,5})$";
+ return Pattern.matches(hostReg, host);
+
+ }
+
+ public static boolean ipRegExpTest(String ip){
+
+ String hostReg = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
+ return Pattern.matches(hostReg, ip);
+
+ }
+
+ public static boolean portRegExpTest(String port){
+
+ String hostReg = "^\\d{1,5}$";
+ if(Pattern.matches(hostReg, port)){
+ int iport=Integer.parseInt(port);
+ if(iport>=1 && iport<=65535) return true;
+ }
+
+ return false;
+
+ }
+
+public static boolean versionRegExpTest(String version){
+
+ String versionReg = "^v\\d+(\\.\\d+)?$";
+ return Pattern.matches(versionReg, version);
+
+ }
+
+public static boolean urlRegExpTest(String url){
+ if(url.equals("/")) return true;
+
+ String urlReg = "^\\/.*((?!\\/).)$";
+ return Pattern.matches(urlReg, url);
+
+}
+
+public static boolean serviceNameRegExpTest(String serviceName){
+
+ String serviceNameReg = "^([0-9a-zA-Z]|-|_)*$";
+ return Pattern.matches(serviceNameReg, serviceName);
+
+}
+
+public static boolean apiRouteUrlRegExpTest(String url){
+
+ String urlReg = "^\\/api\\/.*$";
+ return Pattern.matches(urlReg, url);
+
+}
+
+public static boolean labelRegExpTest(String label){
+
+ String labelReg = "^\\S+:\\S+$";
+ String[] labelArray=StringUtils.split(label,",");
+ for(int i=0;i<labelArray.length;i++){
+ if(!Pattern.matches(labelReg, labelArray[i])){
+ return false;
+ }
+ }
+ return true;
+
+}
+
+
+ public static void main(String[] args) {
+
+ System.out.println(httpUrlRegExpTest("/wqew"));
+ }
+}