This is an automated email from the ASF dual-hosted git repository.

more pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 0ec8ce1  KNOX-2287 KnoxCLI convert topology to provider and descriptor 
(#292)
0ec8ce1 is described below

commit 0ec8ce1c9a160281cf5381611a10a20f8c394602
Author: Sandeep MorĂ© <[email protected]>
AuthorDate: Wed Mar 18 13:57:02 2020 -0400

    KNOX-2287 KnoxCLI convert topology to provider and descriptor (#292)
---
 .../org/apache/knox/gateway/GatewayMessages.java   |  12 +
 .../gateway/model/DescriptorConfiguration.java     | 126 ++++++
 .../knox/gateway/model/ProviderConfiguration.java  |  41 ++
 .../org/apache/knox/gateway/model/Topology.java    | 477 +++++++++++++++++++++
 .../java/org/apache/knox/gateway/util/KnoxCLI.java | 175 +++++++-
 .../knox/gateway/util/TopologyToDescriptor.java    | 270 ++++++++++++
 .../org/apache/knox/gateway/util/KnoxCLITest.java  |  82 ++++
 gateway-server/src/test/resources/token-test.xml   |  70 +++
 8 files changed, 1249 insertions(+), 4 deletions(-)

diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
index 46f6ba8..e37f40a 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
@@ -682,4 +682,16 @@ public interface GatewayMessages {
 
   @Message(level = MessageLevel.ERROR, text = "Failed to save gateway status")
   void failedToSaveGatewayStatus();
+
+  @Message(level = MessageLevel.ERROR, text = "Error validating topology {0}")
+  void errorValidatingTopology(String topologyName);
+
+  @Message(level = MessageLevel.ERROR, text = "Error parsing topology {0}")
+  void errorParsingTopology(String topologyName);
+
+  @Message(level = MessageLevel.ERROR, text = "Error creating provider 
configuration {0} from topology {1}, cause: {2}")
+  void errorSavingProviderConfiguration(String providerPath, String 
topologyName, String message);
+
+  @Message(level = MessageLevel.ERROR, text = "Error creating provider 
descriptor {0} from topology {1}, cause: {2}")
+  void errorSavingDescriptorConfiguration(String providerPath, String 
topologyName, String message);
 }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/model/DescriptorConfiguration.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/model/DescriptorConfiguration.java
new file mode 100644
index 0000000..74b1d87
--- /dev/null
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/model/DescriptorConfiguration.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class DescriptorConfiguration {
+  @JsonProperty("discovery-type")
+  private String discoveryType;
+
+  @JsonProperty("discovery-address")
+  private String discoveryAddress;
+
+  @JsonProperty("discovery-user")
+  private String discoveryUser;
+
+  @JsonProperty("discovery-pwd-alias")
+  private String discoveryPasswordAlias;
+
+  @JsonProperty("provider-config-ref")
+  private String providerConfig;
+
+  @JsonProperty("cluster")
+  private String cluster;
+
+  @JsonProperty("services")
+  private List<Topology.Service> services;
+
+  @JsonProperty("applications")
+  private List<Topology.Application> applications;
+
+  private String name;
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public DescriptorConfiguration() {
+    super();
+  }
+
+  public String getDiscoveryType() {
+    return discoveryType;
+  }
+
+  public void setDiscoveryType(String discoveryType) {
+    this.discoveryType = discoveryType;
+  }
+
+  public String getDiscoveryAddress() {
+    return discoveryAddress;
+  }
+
+  public void setDiscoveryAddress(String discoveryAddress) {
+    this.discoveryAddress = discoveryAddress;
+  }
+
+  public String getDiscoveryUser() {
+    return discoveryUser;
+  }
+
+  public void setDiscoveryUser(String discoveryUser) {
+    this.discoveryUser = discoveryUser;
+  }
+
+  public String getDiscoveryPasswordAlias() {
+    return discoveryPasswordAlias;
+  }
+
+  public void setDiscoveryPasswordAlias(String discoveryPasswordAlias) {
+    this.discoveryPasswordAlias = discoveryPasswordAlias;
+  }
+
+  public String getProviderConfig() {
+    return providerConfig;
+  }
+
+  public void setProviderConfig(String providerConfig) {
+    this.providerConfig = providerConfig;
+  }
+
+  public String getCluster() {
+    return cluster;
+  }
+
+  public void setCluster(String cluster) {
+    this.cluster = cluster;
+  }
+
+  public List<Topology.Service> getServices() {
+    return services;
+  }
+
+  public void setServices(List<Topology.Service> services) {
+    this.services = services;
+  }
+
+  public List<Topology.Application> getApplications() {
+    return applications;
+  }
+
+  public void setApplications(List<Topology.Application> applications) {
+    this.applications = applications;
+  }
+}
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/model/ProviderConfiguration.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/model/ProviderConfiguration.java
new file mode 100644
index 0000000..f05a358
--- /dev/null
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/model/ProviderConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class ProviderConfiguration {
+
+  @JsonProperty("providers")
+  private List<Topology.Provider> providers;
+
+  public ProviderConfiguration() {
+    super();
+  }
+
+  public List<Topology.Provider> getProviders() {
+    return providers;
+  }
+
+  public void setProviders(List<Topology.Provider> providers) {
+    this.providers = providers;
+  }
+
+}
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/model/Topology.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/model/Topology.java
new file mode 100644
index 0000000..419b652
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/model/Topology.java
@@ -0,0 +1,477 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@XmlRootElement(name = "topology")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Topology {
+
+  @XmlElement(name = "provider")
+  @XmlElementWrapper(name = "gateway")
+  public List<Provider> providers;
+  @XmlElement(name = "service")
+  public List<Service> services;
+  @XmlElement
+  private URI uri;
+  @XmlElement
+  private String name;
+  @XmlElement
+  private String path;
+  @XmlElement
+  private long timestamp;
+  @XmlElement(name = "generated")
+  private boolean isGenerated;
+  @XmlElement(name = "application")
+  private List<Application> applications;
+
+  public Topology() {
+  }
+
+  public URI getUri() {
+    return uri;
+  }
+
+  public void setUri(URI uri) {
+    this.uri = uri;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public String getPath() {
+    return path;
+  }
+
+  public void setPath(String defaultServicePath) {
+    this.path = defaultServicePath;
+  }
+
+  public boolean isGenerated() {
+    return isGenerated;
+  }
+
+  public void setGenerated(boolean isGenerated) {
+    this.isGenerated = isGenerated;
+  }
+
+  public List<Service> getServices() {
+    if (services == null) {
+      services = new ArrayList<>();
+    }
+    return services;
+  }
+
+  public void setServices(List<Service> services) {
+    this.services = services;
+  }
+
+  public List<Application> getApplications() {
+    if (applications == null) {
+      applications = new ArrayList<>();
+    }
+    return applications;
+  }
+
+  public void setApplications(List<Application> applications) {
+    this.applications = applications;
+  }
+
+  public List<Provider> getProviders() {
+    if (providers == null) {
+      providers = new ArrayList<>();
+    }
+    return providers;
+  }
+
+  public void setProviders(List<Provider> providers) {
+    this.providers = providers;
+  }
+
+  @XmlAccessorType(XmlAccessType.NONE)
+  public static class Service {
+    @XmlElement
+    private String role;
+
+    @XmlElement
+    private String name;
+
+    @JsonProperty("version")
+    @XmlElement
+    private String version;
+
+    @XmlElement(name = "param")
+    @JsonDeserialize(using = ParamDeserializer.class)
+    private List<Param> params;
+
+    @JsonProperty("urls")
+    @XmlElement(name = "url")
+    private List<String> urls;
+
+    public Service() {
+    }
+
+    @JsonProperty("name")
+    public String getRole() {
+      return role;
+    }
+
+    public void setRole(String role) {
+      this.role = role;
+    }
+
+    @JsonIgnore
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public String getVersion() {
+      return version;
+    }
+
+    public void setVersion(String version) {
+      this.version = version;
+    }
+
+    public List<String> getUrls() {
+      if (urls == null) {
+        urls = new ArrayList<>();
+      }
+      return urls;
+    }
+
+    public void setUrls(List<String> urls) {
+      this.urls = urls;
+    }
+
+    public List<Param> getParams() {
+      if (params == null) {
+        params = new ArrayList<>();
+      }
+      return params;
+    }
+
+    public void setParams(List<Param> params) {
+      this.params = params;
+    }
+
+    @JsonProperty("params")
+    public Map<String, String> getJsonParams() {
+      Map<String, String> result = new LinkedHashMap<>();
+      this.getParams().forEach(p -> result.put(p.getName(), p.getValue()));
+      return result;
+    }
+  }
+
+  @XmlAccessorType(XmlAccessType.NONE)
+  @JsonPropertyOrder({ "role", "name", "enabled", "param" })
+  public static class Provider {
+
+    private static Map<String, Integer> SHIRO_PROVIDER_PARAM_ORDER = new 
HashMap<>();
+
+    static {
+      SHIRO_PROVIDER_PARAM_ORDER.put("sessionTimeout", 0);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapRealm", 1);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapContextFactory", 2);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapGroupContextFactory", 3);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapRealm.contextFactory", 4);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapRealm.userDnTemplate", 5);
+      SHIRO_PROVIDER_PARAM_ORDER.put("main.ldapRealm.contextFactory.url", 6);
+      SHIRO_PROVIDER_PARAM_ORDER
+          .put("main.ldapRealm.contextFactory.authenticationMechanism", 7);
+      SHIRO_PROVIDER_PARAM_ORDER.put("urls./**", 8);
+    }
+
+    @JsonProperty("role")
+    @XmlElement
+    private String role;
+    @JsonProperty("name")
+    @XmlElement
+    private String name;
+    @XmlElement
+    private boolean enabled;
+    @XmlElement(name = "param")
+    @JsonDeserialize(using = ParamDeserializer.class)
+    private List<Param> params;
+
+    public Provider() {
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    @JsonProperty("enabled")
+    public String isEnabled() {
+      return Boolean.toString(enabled);
+    }
+
+    public void setEnabled(boolean enabled) {
+      this.enabled = enabled;
+    }
+
+    public String getRole() {
+      return role;
+    }
+
+    public void setRole(String role) {
+      this.role = role;
+    }
+
+    public List<Param> getParams() {
+      /* for Shiro provider order is important */
+      if ("ShiroProvider".equalsIgnoreCase(name) && params != null && 
!params.isEmpty()) {
+        params.sort(Comparator.comparing((Param p) -> 
SHIRO_PROVIDER_PARAM_ORDER
+            .getOrDefault(p.getName(), Integer.MAX_VALUE)).thenComparing(
+            (Param p) -> SHIRO_PROVIDER_PARAM_ORDER.getOrDefault(p.getName(), 
Integer.MAX_VALUE)));
+      }
+      if (params == null) {
+        params = new ArrayList<>();
+      }
+      return params;
+    }
+
+    public void setParams(List<Param> params) {
+      this.params = params;
+    }
+
+    @JsonProperty("params")
+    public Map<String, String> getJsonParams() {
+      Map<String, String> result = new LinkedHashMap<>();
+      this.getParams().forEach(p -> result.put(p.getName(), p.getValue()));
+      return result;
+    }
+  }
+
+  public static class Descriptor {
+    @JsonProperty("discovery-type")
+    private String discoveryType;
+
+    @JsonProperty("discovery-address")
+    private String discoveryAddress;
+
+    @JsonProperty("discovery-user")
+    private String discoveryUser;
+
+    @JsonProperty("discovery-pwd-alias")
+    private String discoveryPasswordAlias;
+
+    @JsonProperty("provider-config-ref")
+    private String providerConfig;
+
+    @JsonProperty("cluster")
+    private String cluster;
+
+    @JsonProperty("services")
+    private List<Service> services;
+
+    @JsonProperty("applications")
+    private List<Application> applications;
+
+    private String name;
+
+    public Descriptor() {
+      super();
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public String getDiscoveryType() {
+      return discoveryType;
+    }
+
+    public void setDiscoveryType(String discoveryType) {
+      this.discoveryType = discoveryType;
+    }
+
+    public String getDiscoveryAddress() {
+      return discoveryAddress;
+    }
+
+    public void setDiscoveryAddress(String discoveryAddress) {
+      this.discoveryAddress = discoveryAddress;
+    }
+
+    public String getDiscoveryUser() {
+      return discoveryUser;
+    }
+
+    public void setDiscoveryUser(String discoveryUser) {
+      this.discoveryUser = discoveryUser;
+    }
+
+    public String getDiscoveryPasswordAlias() {
+      return discoveryPasswordAlias;
+    }
+
+    public void setDiscoveryPasswordAlias(String discoveryPasswordAlias) {
+      this.discoveryPasswordAlias = discoveryPasswordAlias;
+    }
+
+    public String getProviderConfig() {
+      return providerConfig;
+    }
+
+    public void setProviderConfig(String providerConfig) {
+      this.providerConfig = providerConfig;
+    }
+
+    public String getCluster() {
+      return cluster;
+    }
+
+    public void setCluster(String cluster) {
+      this.cluster = cluster;
+    }
+
+    public List<Service> getServices() {
+      return services;
+    }
+
+    public void setServices(List<Service> services) {
+      this.services = services;
+    }
+
+    public List<Application> getApplications() {
+      return applications;
+    }
+
+    public void setApplications(List<Application> applications) {
+      this.applications = applications;
+    }
+  }
+
+  @XmlAccessorType(XmlAccessType.NONE)
+  public static class Application extends Service {
+
+    @Override
+    public String getRole() {
+      return getName();
+    }
+
+    @Override
+    public void setRole(String role) {
+      setName(role);
+    }
+
+  }
+
+  @XmlAccessorType(XmlAccessType.NONE)
+  public static class Param {
+
+    @XmlElement
+    private String name;
+    @XmlElement
+    private String value;
+
+    public Param() {
+    }
+
+    public Param(String name, String value) {
+      this.name = name;
+      this.value = value;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
+    public String getValue() {
+      return value;
+    }
+
+    public void setValue(String value) {
+      this.value = value;
+    }
+  }
+
+  /* custom deserializer for params field */
+  public static class ParamDeserializer extends JsonDeserializer<List> {
+    final ObjectMapper mapper = new ObjectMapper();
+    @Override
+    public List<Topology.Param> deserialize(final JsonParser jsonParser,
+        final DeserializationContext deserializationContext)
+        throws IOException {
+
+      final JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+      final Map<String, String> result = mapper
+          .convertValue(node, new TypeReference<Map<String, String>>() {
+          });
+      final List<Topology.Param> params = new ArrayList();
+      result.forEach((k,v) -> params.add(new Param(k, v)));
+      return params;
+    }
+  }
+
+}
+
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index 7b69a15..9e5ab5d 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -19,6 +19,8 @@ package org.apache.knox.gateway.util;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configured;
 import org.apache.hadoop.util.Tool;
@@ -33,10 +35,10 @@ import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
 import org.apache.knox.gateway.deploy.DeploymentFactory;
 import org.apache.knox.gateway.services.CLIGatewayServices;
-import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.Service;
 import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.ServiceType;
 import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
 import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
 import org.apache.knox.gateway.services.security.AliasService;
@@ -112,7 +114,8 @@ public class KnoxCLI extends Configured implements Tool {
       "   [" + RemoteRegistryUploadDescriptorCommand.USAGE + "]\n" +
       "   [" + RemoteRegistryDeleteProviderConfigCommand.USAGE + "]\n" +
       "   [" + RemoteRegistryDeleteDescriptorCommand.USAGE + "]\n" +
-      "   [" + RemoteRegistryGetACLCommand.USAGE + "]\n";
+      "   [" + RemoteRegistryGetACLCommand.USAGE + "]\n" +
+      "   [" + TopologyConverter.USAGE + "]\n";
 
   /** allows stdout to be captured if necessary */
   public PrintStream out = System.out;
@@ -136,9 +139,18 @@ public class KnoxCLI extends Configured implements Tool {
   private String remoteRegistryClient;
   private String remoteRegistryEntryName;
 
+  private String type;
+  private String topologyName;
+  private String providerName;
+  private String descriptorName;
+  private String outputDir;
+  private String discoveryUrl;
+  private String discoveryUser;
+  private String discoveryPasswordAlias;
+  private String discoveryType;
+
   // For testing only
   private String master;
-  private String type;
 
   @Override
   public int run(String[] args) throws Exception {
@@ -316,6 +328,54 @@ public class KnoxCLI extends Configured implements Tool {
           return -1;
         }
         this.port = args[++i];
+      } else if (args[i].equals("--provider-name")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.providerName = args[++i];
+      } else if (args[i].equals("--topology-name")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.topologyName = args[++i];
+      } else if (args[i].equals("--descriptor-name")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.descriptorName = args[++i];
+      } else if (args[i].equals("--output-dir")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.outputDir = args[++i];
+      } else if (args[i].equals("--discovery-url")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.discoveryUrl = args[++i];
+      } else if (args[i].equals("--discovery-user")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.discoveryUser = args[++i];
+      } else if (args[i].equals("--discovery-pwd-alias")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.discoveryPasswordAlias = args[++i];
+      } else if (args[i].equals("--discovery-type")) {
+        if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
+          printKnoxShellUsage();
+          return -1;
+        }
+        this.discoveryType = args[++i];
       } else if (args[i].equals("--master")) {
         // For testing only
         if( i+1 >= args.length || args[i+1].startsWith( "-" ) ) {
@@ -407,9 +467,16 @@ public class KnoxCLI extends Configured implements Tool {
           printKnoxShellUsage();
           return -1;
         }
+      } else if (args[i].equalsIgnoreCase("convert-topology")) {
+        if (args.length >= 5) {
+          command = new TopologyConverter();
+        }
+        else {
+          printKnoxShellUsage();
+          return -1;
+        }
       } else {
         printKnoxShellUsage();
-        //ToolRunner.printGenericCommandUsage(System.err);
         return -1;
       }
     }
@@ -489,6 +556,9 @@ public class KnoxCLI extends Configured implements Tool {
       out.println(RemoteRegistryDeleteDescriptorCommand.USAGE + "\n\n" + 
RemoteRegistryDeleteDescriptorCommand.DESC);
       out.println();
       out.println( div );
+      out.println(TopologyConverter.USAGE + "\n\n" + TopologyConverter.DESC);
+      out.println();
+      out.println( div );
     }
   }
 
@@ -2090,6 +2160,103 @@ public class KnoxCLI extends Configured implements Tool 
{
     }
   }
 
+  public class TopologyConverter extends Command {
+
+    public static final String USAGE =
+        "convert-topology --path \"path/to/topology.xml\" --provider-name 
my-provider.json [--descriptor-name my-descriptor.json] "
+            + "[--topology-name topologyName] [--output-path 
\"path/to/configs/\"] [--force] [--cluster clusterName] [--discovery-url url] "
+            + "[--discovery-user discoveryUser] [--discovery-pwd-alias 
discoveryPasswordAlias] [--discovery-type discoveryType]";
+    public static final String DESC =
+        "Convert Knox topology file to provider and descriptor config files \n"
+            + "Options are as follows: \n"
+            + "--path (required) path to topology xml file \n"
+            + "--provider-name (required) name of the provider json config 
file (including .json extension) \n"
+            + "--descriptor-name (optional) name of descriptor json config 
file (including .json extension) \n"
+            + "--topology-name (optional) topology-name can be use instead of 
--path option, if used, KnoxCLI will attempt to find topology from deployed 
topologies.\n"
+            + "\t if not provided topology name will be used as descriptor 
name \n"
+            + "--output-path (optional) output directory to save provider and 
descriptor config files \n"
+            + "\t if not provided config files will be saved in appropriate 
Knox config directory \n"
+            + "--force (optional) force rewriting of existing files, if not 
used, command will fail when the configs files with same name already exist. \n"
+            + "--cluster (optional) cluster name, required for service 
discovery \n"
+            + "--discovery-url (optional) service discovery URL, required for 
service discovery \n"
+            + "--discovery-user (optional) service discovery user, required 
for service discovery \n"
+            + "--discovery-pwd-alias (optional) password alias for service 
discovery user, required for service discovery \n"
+            + "--discovery-type (optional) service discovery type, required 
for service discovery \n";
+
+    public TopologyConverter() {
+      super();
+    }
+
+    @Override
+    public void execute() throws Exception {
+      if (StringUtils.isBlank(FilenameUtils.getExtension(providerName))
+          || StringUtils.isBlank(FilenameUtils.getExtension(descriptorName))) {
+        throw new IllegalArgumentException(
+            " JSON extension is required for provider and descriptor file 
names");
+      }
+
+      final TopologyToDescriptor converter = new TopologyToDescriptor();
+
+      converter.setForce(force);
+      if (!StringUtils.isBlank(topologyName)) {
+        converter.setTopologyPath(
+            getGatewayConfig().getGatewayTopologyDir() + File.separator
+                + topologyName);
+      } else if (!StringUtils.isBlank(path)) {
+        converter.setTopologyPath(path);
+      } else {
+        throw new IllegalArgumentException(
+            "Please specify either --path or --topology-name option");
+      }
+      if (!StringUtils.isBlank(providerName)) {
+        converter.setProviderName(providerName);
+      }
+      if (!StringUtils.isBlank(descriptorName)) {
+        converter.setDescriptorName(descriptorName);
+      }
+      /* if output location is provided then use it */
+      if (!StringUtils.isBlank(outputDir)) {
+        converter.setProviderConfigDir(outputDir);
+        converter.setDescriptorConfigDir(outputDir);
+      } else {
+        converter.setProviderConfigDir(
+            getGatewayConfig().getGatewayProvidersConfigDir());
+        converter.setDescriptorConfigDir(
+            getGatewayConfig().getGatewayDescriptorsDir());
+      }
+      /* set discovery params */
+      if (!StringUtils.isBlank(cluster)) {
+        converter.setCluster(cluster);
+      }
+      if (!StringUtils.isBlank(discoveryUrl)) {
+        converter.setDiscoveryUrl(discoveryUrl);
+      }
+      if (!StringUtils.isBlank(discoveryUser)) {
+        converter.setDiscoveryUser(discoveryUser);
+      }
+      if (!StringUtils.isBlank(discoveryPasswordAlias)) {
+        converter.setDiscoveryPasswordAlias(discoveryPasswordAlias);
+      }
+      if (!StringUtils.isBlank(discoveryType)) {
+        converter.setDiscoveryType(discoveryType);
+      }
+
+      converter.validate();
+      converter.convert();
+
+      final String topoName = StringUtils.isBlank(topologyName) ?  
FilenameUtils.getBaseName(path) : topologyName;
+      out.println(
+          "Provider " + providerName + " and descriptor " + descriptorName
+              + " generated for topology " + topoName
+              + "\n");
+    }
+
+    @Override
+    public String getUsage() {
+      return USAGE + ":\n\n" + DESC;
+    }
+
+  }
 
   private static Properties loadBuildProperties() {
     Properties properties = new Properties();
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/util/TopologyToDescriptor.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/TopologyToDescriptor.java
new file mode 100644
index 0000000..852d937
--- /dev/null
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/TopologyToDescriptor.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.knox.gateway.GatewayMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.model.DescriptorConfiguration;
+import org.apache.knox.gateway.model.ProviderConfiguration;
+import org.apache.knox.gateway.model.Topology;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Locale;
+
+/**
+ * A helper class to convert topology xml file to descriptor and provider
+ * model.
+ */
+public class TopologyToDescriptor {
+
+  private static final GatewayMessages LOG = MessagesFactory
+      .get(GatewayMessages.class);
+  private static final ObjectMapper mapper = new ObjectMapper();
+  private static final String SCHEMA_FILE = "/conf/topology-v1.xsd";
+
+  static {
+    /* skip printing out null fields */
+    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+  }
+
+  private String topologyPath;
+  private String providerName;
+  private String descriptorName;
+  private String discoveryUrl;
+  private String discoveryUser;
+  private String discoveryPasswordAlias;
+  private String discoveryType;
+  private String cluster;
+  private String providerConfigDir;
+  private String descriptorConfigDir;
+  private boolean force;
+
+  public TopologyToDescriptor() {
+    super();
+  }
+
+  /**
+   * A function that validates the given topology
+   */
+  private void validateTopology(final String xsd, final String topologyFile)
+      throws IOException, SAXException {
+    try (InputStream topologyFileStream = Files
+        .newInputStream(Paths.get(topologyFile))) {
+      final Source xmlSource = new StreamSource(topologyFileStream);
+      final Schema schema = getSchema(xsd);
+      final Validator validator = schema.newValidator();
+      validator.validate(xmlSource);
+    } catch (IOException | SAXException e) {
+      LOG.errorValidatingTopology(topologyFile);
+      throw e;
+    }
+  }
+
+  private Topology parseTopology(final String xsd, final String topologyFile)
+      throws JAXBException, SAXException, IOException {
+    try (InputStream topologyFileStream = Files
+        .newInputStream(Paths.get(topologyFile))) {
+      final Schema schema = getSchema(xsd);
+      final JAXBContext jc = JAXBContext.newInstance(Topology.class);
+      final Unmarshaller unmarshaller = jc.createUnmarshaller();
+      unmarshaller.setSchema(schema);
+      return (Topology) unmarshaller.unmarshal(topologyFileStream);
+    } catch (SAXException | JAXBException | IOException e) {
+      LOG.errorParsingTopology(topologyFile);
+      throw e;
+    }
+  }
+
+  private Schema getSchema(final String xsd) throws SAXException {
+    final SchemaFactory schemaFactory = SchemaFactory
+        .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+    final URL schemaUrl = TopologyToDescriptor.class.getResource(xsd);
+    return schemaFactory.newSchema(schemaUrl);
+  }
+
+  /**
+   * Validate topology
+   */
+  public void validate() throws IOException, SAXException {
+    validateTopology(SCHEMA_FILE, topologyPath);
+  }
+
+  /**
+   * Convert topology to provider and descriptor
+   */
+  public void convert() throws IOException, JAXBException, SAXException {
+    final Topology topology = parseTopology(SCHEMA_FILE, topologyPath);
+    saveProvider(topology);
+    saveDescriptor(topology, providerName);
+  }
+
+  private void saveProvider(final Topology topology) throws IOException {
+    try {
+      final ProviderConfiguration provider = new ProviderConfiguration();
+      if (topology.getProviders() != null) {
+        provider.setProviders(topology.getProviders());
+      }
+
+      final File providerFile = new File(
+          providerConfigDir + File.separator + providerName);
+
+      fileCheck(providerFile);
+
+      mapper.writerWithDefaultPrettyPrinter()
+          .writeValue(providerFile, provider);
+    } catch (final IOException e) {
+      LOG.errorSavingProviderConfiguration(providerName, topologyPath,
+          e.toString());
+      throw e;
+    }
+  }
+
+  private void saveDescriptor(final Topology topology,
+      final String providerName) throws IOException {
+    final DescriptorConfiguration descriptorConfiguration = new 
DescriptorConfiguration();
+
+    descriptorConfiguration
+        .setProviderConfig(FilenameUtils.removeExtension(providerName));
+
+    if (!StringUtils.isBlank(discoveryUrl)) {
+      descriptorConfiguration.setDiscoveryAddress(discoveryUrl);
+    }
+
+    if (!StringUtils.isBlank(discoveryUser)) {
+      descriptorConfiguration.setDiscoveryUser(discoveryUser);
+    }
+
+    if (!StringUtils.isBlank(discoveryPasswordAlias)) {
+      
descriptorConfiguration.setDiscoveryPasswordAlias(discoveryPasswordAlias);
+    }
+
+    if (!StringUtils.isBlank(discoveryType)) {
+      descriptorConfiguration.setDiscoveryType(discoveryType);
+    }
+
+    if (!StringUtils.isBlank(cluster)) {
+      descriptorConfiguration.setCluster(cluster);
+    }
+
+    if (topology.getName() != null) {
+      descriptorConfiguration.setName(topology.getName());
+    }
+
+    if (topology.getApplications() != null) {
+      descriptorConfiguration.setApplications(topology.getApplications());
+    }
+
+    if (topology.getServices() != null) {
+      descriptorConfiguration.setServices(topology.getServices());
+    }
+
+    final File descriptorFile = new File(
+        descriptorConfigDir + File.separator + descriptorName);
+
+    fileCheck(descriptorFile);
+
+    try {
+      mapper.writerWithDefaultPrettyPrinter()
+          .writeValue(descriptorFile, descriptorConfiguration);
+    } catch (IOException e) {
+      LOG.errorSavingDescriptorConfiguration(descriptorName, topologyPath,
+          e.toString());
+      throw e;
+    }
+  }
+
+  /**
+   * Check whether the file exists and can be overwritten.
+   *
+   * @param file
+   * @throws IOException
+   */
+  private void fileCheck(final File file) throws IOException {
+    if (!force && file.exists()) {
+      throw new IOException(String
+          .format(Locale.ROOT, "File %s already exist, use --force option to 
overwrite.",
+              file.getAbsolutePath()));
+    }
+    /* make sure file and directories are in place */
+    Files.createDirectories(file.toPath().getParent());
+    file.createNewFile();
+  }
+
+  public void setDiscoveryUrl(String discoveryUrl) {
+    this.discoveryUrl = discoveryUrl;
+  }
+
+  public void setDiscoveryUser(String discoveryUser) {
+    this.discoveryUser = discoveryUser;
+  }
+
+  public void setDiscoveryPasswordAlias(String discoveryPasswordAlias) {
+    this.discoveryPasswordAlias = discoveryPasswordAlias;
+  }
+
+  public void setDiscoveryType(String discoveryType) {
+    this.discoveryType = discoveryType;
+  }
+
+  public void setCluster(String cluster) {
+    this.cluster = cluster;
+  }
+
+  public void setTopologyPath(String topologyPath) {
+    this.topologyPath = topologyPath;
+  }
+
+  public void setProviderName(String providerName) {
+    this.providerName = providerName;
+  }
+
+  public void setDescriptorName(String descriptorName) {
+    this.descriptorName = descriptorName;
+  }
+
+  public void setProviderConfigDir(String providerConfigDir) {
+    this.providerConfigDir = providerConfigDir;
+  }
+
+  public void setDescriptorConfigDir(String descriptorConfigDir) {
+    this.descriptorConfigDir = descriptorConfigDir;
+  }
+
+  public void setForce(boolean force) {
+    this.force = force;
+  }
+}
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java 
b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
index f2ce5f3..8e5995c 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
@@ -17,11 +17,14 @@
  */
 package org.apache.knox.gateway.util;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.mycila.xmltool.XMLDoc;
 import com.mycila.xmltool.XMLTag;
 import org.apache.commons.io.FileUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.model.DescriptorConfiguration;
+import org.apache.knox.gateway.model.ProviderConfiguration;
 import org.apache.knox.gateway.services.ServiceType;
 import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
 import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
@@ -39,6 +42,7 @@ import java.io.PrintStream;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.UUID;
 
 import static org.hamcrest.CoreMatchers.containsString;
@@ -1047,6 +1051,84 @@ public class KnoxCLITest {
 
   }
 
+  /* Test cli command to convert topology to providers and descriptors */
+  @Test
+  public void testConvertTopology() throws Exception {
+    outContent.reset();
+    Configuration config = new GatewayConfigImpl();
+    URL topologyFileURL = ClassLoader.getSystemResource("token-test.xml");
+    final File topologyFile = Paths.get(topologyFileURL.toURI()).toFile();
+    final File outputDir = createDir();
+    final String providerConfigFileName = "my-provider.json";
+    final String descriptorConfigFileName = "my-descriptor.json";
+    final String clusterName = "myCluster";
+    final String discoveryUrl = "https://localhost:7183";;
+    final String discoveryUser = "discoveryUser";
+    final String discoveryType = "ClouderaManager";
+    final String discoveryPwdAlias = "discovery";
+    final ObjectMapper mapper = new ObjectMapper();
+
+    try {
+      KnoxCLI cli = new KnoxCLI();
+      cli.setConf(config);
+
+      // This is only to get the gateway services initialized
+      cli.run(new String[]{"convert-topology", "--master", "master",
+          "--path", topologyFile.getAbsolutePath(),
+          "--provider-name", providerConfigFileName,
+          "--descriptor-name", descriptorConfigFileName,
+          "--output-dir", outputDir.getAbsolutePath(),
+          "--force",
+          "--cluster", clusterName,
+          "--discovery-url", discoveryUrl,
+          "--discovery-user", discoveryUser,
+          "--discovery-pwd-alias", discoveryPwdAlias,
+          "--discovery-type", discoveryType});
+
+      final File providerConfigFile = new 
File(outputDir+File.separator+providerConfigFileName);
+      final File descriptorConfigFile = new 
File(outputDir+File.separator+descriptorConfigFileName);
+
+      assertTrue("Provider config file not created", 
providerConfigFile.exists());
+      assertTrue("Descriptor config file not created", 
descriptorConfigFile.exists());
+
+      final ProviderConfiguration providerJson = 
mapper.readValue(providerConfigFile, ProviderConfiguration.class);
+      final DescriptorConfiguration descriptorJson = 
mapper.readValue(descriptorConfigFile, DescriptorConfiguration.class);
+
+      assertNotNull("Provider config could not be deserialized", providerJson);
+      assertNotNull("Descriptor config could not be deserialized", 
descriptorJson);
+
+      assertEquals(providerJson.getProviders().size(), 1);
+      assertEquals(providerJson.getProviders().get(0).getParams().size(), 8);
+      assertEquals(providerJson.getProviders().get(0).getName(), 
"ShiroProvider");
+      assertEquals(providerJson.getProviders().get(0).getRole(), 
"authentication");
+      assertEquals(providerJson.getProviders().get(0).isEnabled(), "true");
+
+      /* test param order */
+      
assertEquals(providerJson.getProviders().get(0).getParams().get(0).getName(), 
"sessionTimeout");
+      
assertEquals(providerJson.getProviders().get(0).getParams().get(3).getName(), 
"main.ldapRealm.contextFactory");
+      
assertEquals(providerJson.getProviders().get(0).getParams().get(3).getName(), 
"main.ldapRealm.contextFactory");
+      
assertEquals(providerJson.getProviders().get(0).getParams().get(5).getValue(), 
"ldap://localhost:33389";);
+      
assertEquals(providerJson.getProviders().get(0).getParams().get(7).getValue(), 
"authcBasic");
+
+      assertEquals(descriptorJson.getDiscoveryType(), discoveryType);
+      assertEquals(descriptorJson.getDiscoveryAddress(), discoveryUrl);
+      assertEquals(descriptorJson.getDiscoveryPasswordAlias(), 
discoveryPwdAlias);
+      assertEquals(descriptorJson.getDiscoveryUser(), discoveryUser);
+      assertEquals(descriptorJson.getCluster(), clusterName);
+      assertEquals(descriptorJson.getServices().size(), 1);
+      assertEquals(descriptorJson.getServices().get(0).getRole(), "KNOXTOKEN");
+      assertEquals(descriptorJson.getServices().get(0).getParams().size(), 5);
+
+    } finally {
+      FileUtils.deleteQuietly(outputDir);
+    }
+  }
+
+  private File createDir() throws IOException {
+    return TestUtils
+        .createTempDir(this.getClass().getSimpleName() + "-");
+  }
+
   private static final String testDescriptorContentJSON = "{\n" +
                                                           "  
\"discovery-address\":\"http://localhost:8080\",\n"; +
                                                           "  
\"discovery-user\":\"maria_dev\",\n" +
diff --git a/gateway-server/src/test/resources/token-test.xml 
b/gateway-server/src/test/resources/token-test.xml
new file mode 100644
index 0000000..f3b6920
--- /dev/null
+++ b/gateway-server/src/test/resources/token-test.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--==============================================-->
+<!-- DO NOT EDIT. This is an auto-generated file. -->
+<!--==============================================-->
+<topology>
+    <generated>true</generated>
+    <gateway>
+        <provider>
+            <role>authentication</role>
+            <name>ShiroProvider</name>
+            <enabled>true</enabled>
+            <param>
+                <name>sessionTimeout</name>
+                <value>20</value>
+            </param>
+            <param>
+                <name>main.ldapRealm</name>
+                <value>org.apache.knox.gateway.shirorealm.KnoxLdapRealm</value>
+            </param>
+            <param>
+                <name>main.ldapContextFactory</name>
+                
<value>org.apache.knox.gateway.shirorealm.KnoxLdapContextFactory</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.contextFactory</name>
+                <value>$ldapContextFactory</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.userDnTemplate</name>
+                <value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
+            </param>
+            <param>
+                <name>main.ldapRealm.contextFactory.url</name>
+                <value>ldap://localhost:33389</value>
+            </param>
+            <param>
+                
<name>main.ldapRealm.contextFactory.authenticationMechanism</name>
+                <value>simple</value>
+            </param>
+            <param>
+                <name>urls./**</name>
+                <value>authcBasic</value>
+            </param>
+        </provider>
+    </gateway>
+
+    <service>
+        <role>KNOXTOKEN</role>
+        <param>
+            <name>knox.token.ttl</name>
+            <value>30000</value>
+        </param>
+        <param>
+            <name>knox.token.audiences</name>
+            <value>idbroker</value>
+        </param>
+        <param>
+            <name>knox.token.exp.server-managed</name>
+            <value>true</value>
+        </param>
+        <param>
+            <name>knox.token.exp.renew-interval</name>
+            <value>60000</value>
+        </param>
+        <param>
+            <name>knox.token.renewer.whitelist</name>
+            <value>admin</value>
+        </param>
+    </service>
+</topology>

Reply via email to