You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/11/02 18:48:21 UTC
[17/25] knox git commit: Merge branch 'master' into
KNOX-998-Package_Restructuring
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java
----------------------------------------------------------------------
diff --cc gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java
index 1861490,0000000..948447b
mode 100644,000000..100644
--- a/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java
+++ b/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java
@@@ -1,312 -1,0 +1,657 @@@
+/**
+ * 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.service.admin;
+
++import com.fasterxml.jackson.annotation.JsonProperty;
++import org.apache.commons.io.FileUtils;
++import org.apache.commons.io.FilenameUtils;
++import org.apache.knox.gateway.i18n.GatewaySpiMessages;
++import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.service.admin.beans.BeanConverter;
+import org.apache.knox.gateway.service.admin.beans.Topology;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.services.topology.TopologyService;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+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 java.io.File;
++import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
++import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
++import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
++
+import static javax.ws.rs.core.Response.ok;
++import static javax.ws.rs.core.Response.created;
++import static javax.ws.rs.core.Response.notModified;
++import static javax.ws.rs.core.Response.status;
++
+
+@Path("/api/v1")
+public class TopologiesResource {
++
++ private static final String XML_EXT = ".xml";
++ private static final String JSON_EXT = ".json";
++
++ private static final String TOPOLOGIES_API_PATH = "topologies";
++ private static final String SINGLE_TOPOLOGY_API_PATH = TOPOLOGIES_API_PATH + "/{id}";
++ private static final String PROVIDERCONFIG_API_PATH = "providerconfig";
++ private static final String SINGLE_PROVIDERCONFIG_API_PATH = PROVIDERCONFIG_API_PATH + "/{name}";
++ private static final String DESCRIPTORS_API_PATH = "descriptors";
++ private static final String SINGLE_DESCRIPTOR_API_PATH = DESCRIPTORS_API_PATH + "/{name}";
++
++ private static GatewaySpiMessages log = MessagesFactory.get(GatewaySpiMessages.class);
++
+ @Context
+ private HttpServletRequest request;
+
+ @GET
+ @Produces({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies/{id}")
++ @Path(SINGLE_TOPOLOGY_API_PATH)
+ public Topology getTopology(@PathParam("id") String id) {
+ GatewayServices services = (GatewayServices) request.getServletContext()
+ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+ GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ for (org.apache.knox.gateway.topology.Topology t : ts.getTopologies()) {
+ if(t.getName().equals(id)) {
+ try {
+ t.setUri(new URI( buildURI(t, config, request) ));
+ } catch (URISyntaxException se) {
+ t.setUri(null);
+ }
+ return BeanConverter.getTopology(t);
+ }
+ }
+ return null;
+ }
+
+ @GET
+ @Produces({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies")
++ @Path(TOPOLOGIES_API_PATH)
+ public SimpleTopologyWrapper getTopologies() {
+ GatewayServices services = (GatewayServices) request.getServletContext()
+ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ ArrayList<SimpleTopology> st = new ArrayList<SimpleTopology>();
+ GatewayConfig conf = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+
+ for (org.apache.knox.gateway.topology.Topology t : ts.getTopologies()) {
+ st.add(getSimpleTopology(t, conf));
+ }
+
+ Collections.sort(st, new TopologyComparator());
+ SimpleTopologyWrapper stw = new SimpleTopologyWrapper();
+
+ for(SimpleTopology t : st){
+ stw.topologies.add(t);
+ }
+
+ return stw;
+
+ }
+
+ @PUT
+ @Consumes({APPLICATION_JSON, APPLICATION_XML})
- @Path("topologies/{id}")
++ @Path(SINGLE_TOPOLOGY_API_PATH)
+ public Topology uploadTopology(@PathParam("id") String id, Topology t) {
+
+ GatewayServices gs = (GatewayServices) request.getServletContext()
+ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ t.setName(id);
+ TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ ts.deployTopology(BeanConverter.getTopology(t));
+
+ return getTopology(id);
+ }
+
+ @DELETE
+ @Produces(APPLICATION_JSON)
- @Path("topologies/{id}")
++ @Path(SINGLE_TOPOLOGY_API_PATH)
+ public Response deleteTopology(@PathParam("id") String id) {
+ boolean deleted = false;
+ if(!"admin".equals(id)) {
+ GatewayServices services = (GatewayServices) request.getServletContext()
+ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
+
+ for (org.apache.knox.gateway.topology.Topology t : ts.getTopologies()) {
+ if(t.getName().equals(id)) {
+ ts.deleteTopology(t);
+ deleted = true;
+ }
+ }
+ }else{
+ deleted = false;
+ }
+ return ok().entity("{ \"deleted\" : " + deleted + " }").build();
+ }
+
++ @GET
++ @Produces({APPLICATION_JSON})
++ @Path(PROVIDERCONFIG_API_PATH)
++ public HrefListing getProviderConfigurations() {
++ HrefListing listing = new HrefListing();
++ listing.setHref(buildHref(request));
++
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ List<HrefListItem> configs = new ArrayList<>();
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++ // Get all the simple descriptor file names
++ for (File providerConfig : ts.getProviderConfigurations()){
++ String id = FilenameUtils.getBaseName(providerConfig.getName());
++ configs.add(new HrefListItem(buildHref(id, request), providerConfig.getName()));
++ }
++
++ listing.setItems(configs);
++ return listing;
++ }
++
++ @GET
++ @Produces({APPLICATION_XML})
++ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
++ public Response getProviderConfiguration(@PathParam("name") String name) {
++ Response response;
++
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++
++ File providerConfigFile = null;
++
++ for (File pc : ts.getProviderConfigurations()){
++ // If the file name matches the specified id
++ if (FilenameUtils.getBaseName(pc.getName()).equals(name)) {
++ providerConfigFile = pc;
++ break;
++ }
++ }
++
++ if (providerConfigFile != null) {
++ byte[] content = null;
++ try {
++ content = FileUtils.readFileToByteArray(providerConfigFile);
++ response = ok().entity(content).build();
++ } catch (IOException e) {
++ log.failedToReadConfigurationFile(providerConfigFile.getAbsolutePath(), e);
++ response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
++ }
++
++ } else {
++ response = Response.status(Response.Status.NOT_FOUND).build();
++ }
++ return response;
++ }
++
++ @DELETE
++ @Produces(APPLICATION_JSON)
++ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
++ public Response deleteProviderConfiguration(@PathParam("name") String name) {
++ Response response;
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++ if (ts.deleteProviderConfiguration(name)) {
++ response = ok().entity("{ \"deleted\" : \"provider config " + name + "\" }").build();
++ } else {
++ response = notModified().build();
++ }
++ return response;
++ }
++
++
++ @DELETE
++ @Produces(APPLICATION_JSON)
++ @Path(SINGLE_DESCRIPTOR_API_PATH)
++ public Response deleteSimpleDescriptor(@PathParam("name") String name) {
++ Response response = null;
++ if(!"admin".equals(name)) {
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++ if (ts.deleteDescriptor(name)) {
++ response = ok().entity("{ \"deleted\" : \"descriptor " + name + "\" }").build();
++ }
++ }
++
++ if (response == null) {
++ response = notModified().build();
++ }
++
++ return response;
++ }
++
++
++ @PUT
++ @Consumes({APPLICATION_XML})
++ @Path(SINGLE_PROVIDERCONFIG_API_PATH)
++ public Response uploadProviderConfiguration(@PathParam("name") String name, String content) {
++ Response response = null;
++
++ GatewayServices gs =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
++
++ boolean isUpdate = configFileExists(ts.getProviderConfigurations(), name);
++
++ String filename = name.endsWith(XML_EXT) ? name : name + XML_EXT;
++ if (ts.deployProviderConfiguration(filename, content)) {
++ try {
++ if (isUpdate) {
++ response = Response.noContent().build();
++ } else{
++ response = created(new URI(buildHref(request))).build();
++ }
++ } catch (URISyntaxException e) {
++ log.invalidResourceURI(e.getInput(), e.getReason(), e);
++ response = status(Response.Status.BAD_REQUEST).entity("{ \"error\" : \"Failed to deploy provider configuration " + name + "\" }").build();
++ }
++ }
++
++ return response;
++ }
++
++
++ private boolean configFileExists(Collection<File> existing, String candidateName) {
++ boolean result = false;
++ for (File exists : existing) {
++ if (FilenameUtils.getBaseName(exists.getName()).equals(candidateName)) {
++ result = true;
++ break;
++ }
++ }
++ return result;
++ }
++
++
++ @PUT
++ @Consumes({APPLICATION_JSON})
++ @Path(SINGLE_DESCRIPTOR_API_PATH)
++ public Response uploadSimpleDescriptor(@PathParam("name") String name, String content) {
++ Response response = null;
++
++ GatewayServices gs =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
++
++ boolean isUpdate = configFileExists(ts.getDescriptors(), name);
++
++ String filename = name.endsWith(JSON_EXT) ? name : name + JSON_EXT;
++ if (ts.deployDescriptor(filename, content)) {
++ try {
++ if (isUpdate) {
++ response = Response.noContent().build();
++ } else {
++ response = created(new URI(buildHref(request))).build();
++ }
++ } catch (URISyntaxException e) {
++ log.invalidResourceURI(e.getInput(), e.getReason(), e);
++ response = status(Response.Status.BAD_REQUEST).entity("{ \"error\" : \"Failed to deploy descriptor " + name + "\" }").build();
++ }
++ }
++
++ return response;
++ }
++
++
++ @GET
++ @Produces({APPLICATION_JSON})
++ @Path(DESCRIPTORS_API_PATH)
++ public HrefListing getSimpleDescriptors() {
++ HrefListing listing = new HrefListing();
++ listing.setHref(buildHref(request));
++
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ List<HrefListItem> descriptors = new ArrayList<>();
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++ for (File descriptor : ts.getDescriptors()){
++ String id = FilenameUtils.getBaseName(descriptor.getName());
++ descriptors.add(new HrefListItem(buildHref(id, request), descriptor.getName()));
++ }
++
++ listing.setItems(descriptors);
++ return listing;
++ }
++
++
++ @GET
++ @Produces({APPLICATION_JSON, TEXT_PLAIN})
++ @Path(SINGLE_DESCRIPTOR_API_PATH)
++ public Response getSimpleDescriptor(@PathParam("name") String name) {
++ Response response;
++
++ GatewayServices services =
++ (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
++
++ TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE);
++
++ File descriptorFile = null;
++
++ for (File sd : ts.getDescriptors()){
++ // If the file name matches the specified id
++ if (FilenameUtils.getBaseName(sd.getName()).equals(name)) {
++ descriptorFile = sd;
++ break;
++ }
++ }
++
++ if (descriptorFile != null) {
++ String mediaType = APPLICATION_JSON;
++
++ byte[] content = null;
++ try {
++ if ("yml".equals(FilenameUtils.getExtension(descriptorFile.getName()))) {
++ mediaType = TEXT_PLAIN;
++ }
++ content = FileUtils.readFileToByteArray(descriptorFile);
++ response = ok().type(mediaType).entity(content).build();
++ } catch (IOException e) {
++ log.failedToReadConfigurationFile(descriptorFile.getAbsolutePath(), e);
++ response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
++ }
++ } else {
++ response = Response.status(Response.Status.NOT_FOUND).build();
++ }
++
++ return response;
++ }
++
+
+ private static class TopologyComparator implements Comparator<SimpleTopology> {
+ @Override
+ public int compare(SimpleTopology t1, SimpleTopology t2) {
+ return t1.getName().compareTo(t2.getName());
+ }
+ }
+
- String buildURI(org.apache.knox.gateway.topology.Topology topology, GatewayConfig config, HttpServletRequest req){
++
++ String buildURI(org.apache.knox.gateway.topology.Topology topology, GatewayConfig config, HttpServletRequest req){
+ String uri = buildXForwardBaseURL(req);
+
- // Strip extra context
++ // Strip extra context
+ uri = uri.replace(req.getContextPath(), "");
+
- // Add the gateway path
++ // Add the gateway path
+ String gatewayPath;
+ if(config.getGatewayPath() != null){
+ gatewayPath = config.getGatewayPath();
+ }else{
+ gatewayPath = "gateway";
+ }
+ uri += "/" + gatewayPath;
+
+ uri += "/" + topology.getName();
+ return uri;
+ }
+
- String buildHref(org.apache.knox.gateway.topology.Topology t, HttpServletRequest req) {
++ String buildHref(HttpServletRequest req) {
++ return buildHref((String)null, req);
++ }
++
++ String buildHref(String id, HttpServletRequest req) {
+ String href = buildXForwardBaseURL(req);
- // Make sure that the pathInfo doesn't have any '/' chars at the end.
++ // Make sure that the pathInfo doesn't have any '/' chars at the end.
+ String pathInfo = req.getPathInfo();
- if(pathInfo.endsWith("/")) {
- while(pathInfo.endsWith("/")) {
- pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
- }
++ while(pathInfo.endsWith("/")) {
++ pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
++ }
++
++ href += pathInfo;
++
++ if (id != null) {
++ href += "/" + id;
+ }
+
- href += pathInfo + "/" + t.getName();
+ return href;
+ }
+
- private SimpleTopology getSimpleTopology(
- org.apache.knox.gateway.topology.Topology t, GatewayConfig config) {
++ String buildHref(org.apache.knox.gateway.topology.Topology t, HttpServletRequest req) {
++ return buildHref(t.getName(), req);
++ }
++
++ private SimpleTopology getSimpleTopology(org.apache.hadoop.gateway.topology.Topology t, GatewayConfig config) {
+ String uri = buildURI(t, config, request);
+ String href = buildHref(t, request);
+ return new SimpleTopology(t, uri, href);
+ }
+
+ private String buildXForwardBaseURL(HttpServletRequest req){
+ final String X_Forwarded = "X-Forwarded-";
+ final String X_Forwarded_Context = X_Forwarded + "Context";
+ final String X_Forwarded_Proto = X_Forwarded + "Proto";
+ final String X_Forwarded_Host = X_Forwarded + "Host";
+ final String X_Forwarded_Port = X_Forwarded + "Port";
+ final String X_Forwarded_Server = X_Forwarded + "Server";
+
+ String baseURL = "";
+
- // Get Protocol
++ // Get Protocol
+ if(req.getHeader(X_Forwarded_Proto) != null){
+ baseURL += req.getHeader(X_Forwarded_Proto) + "://";
+ } else {
+ baseURL += req.getProtocol() + "://";
+ }
+
- // Handle Server/Host and Port Here
++ // Handle Server/Host and Port Here
+ if (req.getHeader(X_Forwarded_Host) != null && req.getHeader(X_Forwarded_Port) != null){
- // Double check to see if host has port
++ // Double check to see if host has port
+ if(req.getHeader(X_Forwarded_Host).contains(req.getHeader(X_Forwarded_Port))){
+ baseURL += req.getHeader(X_Forwarded_Host);
+ } else {
- // If there's no port, add the host and port together;
++ // If there's no port, add the host and port together;
+ baseURL += req.getHeader(X_Forwarded_Host) + ":" + req.getHeader(X_Forwarded_Port);
+ }
+ } else if(req.getHeader(X_Forwarded_Server) != null && req.getHeader(X_Forwarded_Port) != null){
- // Tack on the server and port if they're available. Try host if server not available
++ // Tack on the server and port if they're available. Try host if server not available
+ baseURL += req.getHeader(X_Forwarded_Server) + ":" + req.getHeader(X_Forwarded_Port);
+ } else if(req.getHeader(X_Forwarded_Port) != null) {
- // if we at least have a port, we can use it.
++ // if we at least have a port, we can use it.
+ baseURL += req.getServerName() + ":" + req.getHeader(X_Forwarded_Port);
+ } else {
- // Resort to request members
++ // Resort to request members
+ baseURL += req.getServerName() + ":" + req.getLocalPort();
+ }
+
- // Handle Server context
++ // Handle Server context
+ if( req.getHeader(X_Forwarded_Context) != null ) {
+ baseURL += req.getHeader( X_Forwarded_Context );
+ } else {
+ baseURL += req.getContextPath();
+ }
+
+ return baseURL;
+ }
+
++
++ static class HrefListing {
++ @JsonProperty
++ String href;
++
++ @JsonProperty
++ List<HrefListItem> items;
++
++ HrefListing() {}
++
++ public void setHref(String href) {
++ this.href = href;
++ }
++
++ public String getHref() {
++ return href;
++ }
++
++ public void setItems(List<HrefListItem> items) {
++ this.items = items;
++ }
++
++ public List<HrefListItem> getItems() {
++ return items;
++ }
++ }
++
++ static class HrefListItem {
++ @JsonProperty
++ String href;
++
++ @JsonProperty
++ String name;
++
++ HrefListItem() {}
++
++ HrefListItem(String href, String name) {
++ this.href = href;
++ this.name = name;
++ }
++
++ public void setHref(String href) {
++ this.href = href;
++ }
++
++ public String getHref() {
++ return href;
++ }
++
++ public void setName(String name) {
++ this.name = name;
++ }
++ public String getName() {
++ return name;
++ }
++ }
++
++
+ @XmlAccessorType(XmlAccessType.NONE)
+ public static class SimpleTopology {
+
+ @XmlElement
+ private String name;
+ @XmlElement
+ private String timestamp;
+ @XmlElement
++ private String defaultServicePath;
++ @XmlElement
+ private String uri;
+ @XmlElement
+ private String href;
+
+ public SimpleTopology() {}
+
+ public SimpleTopology(org.apache.knox.gateway.topology.Topology t, String uri, String href) {
+ this.name = t.getName();
+ this.timestamp = Long.toString(t.getTimestamp());
++ this.defaultServicePath = t.getDefaultServicePath();
+ this.uri = uri;
+ this.href = href;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String n) {
+ name = n;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
++ public void setDefaultService(String defaultServicePath) {
++ this.defaultServicePath = defaultServicePath;
++ }
++
++ public String getDefaultService() {
++ return defaultServicePath;
++ }
++
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public String getHref() {
+ return href;
+ }
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+ }
+
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class SimpleTopologyWrapper{
+
+ @XmlElement(name="topology")
+ @XmlElementWrapper(name="topologies")
+ private List<SimpleTopology> topologies = new ArrayList<SimpleTopology>();
+
+ public List<SimpleTopology> getTopologies(){
+ return topologies;
+ }
+
+ public void setTopologies(List<SimpleTopology> ts){
+ this.topologies = ts;
+ }
+
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/BeanConverter.java
----------------------------------------------------------------------
diff --cc gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/BeanConverter.java
index 358b5b5,0000000..e8d6915
mode 100644,000000..100644
--- a/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/BeanConverter.java
+++ b/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/BeanConverter.java
@@@ -1,168 -1,0 +1,170 @@@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.service.admin.beans;
+
+import org.apache.knox.gateway.topology.Version;
+
+import java.util.Collection;
+
+public class BeanConverter {
+
+ public static Topology getTopology(
+ org.apache.knox.gateway.topology.Topology topology) {
+ Topology topologyResource = new Topology();
+ topologyResource.setName(topology.getName());
+ topologyResource.setTimestamp(topology.getTimestamp());
++ topologyResource.setPath(topology.getDefaultServicePath());
+ topologyResource.setUri(topology.getUri());
+ for ( org.apache.knox.gateway.topology.Provider provider : topology.getProviders() ) {
+ topologyResource.getProviders().add( getProvider(provider) );
+ }
+ for ( org.apache.knox.gateway.topology.Service service : topology.getServices() ) {
+ topologyResource.getServices().add( getService(service) );
+ }
+ for ( org.apache.knox.gateway.topology.Application application : topology.getApplications() ) {
+ topologyResource.getApplications().add( getApplication(application) );
+ }
+ return topologyResource;
+ }
+
+ public static org.apache.knox.gateway.topology.Topology getTopology(Topology topology) {
+ org.apache.knox.gateway.topology.Topology deploymentTopology = new org.apache.knox.gateway.topology.Topology();
+ deploymentTopology.setName(topology.getName());
+ deploymentTopology.setTimestamp(topology.getTimestamp());
++ deploymentTopology.setDefaultServicePath(topology.getPath());
+ deploymentTopology.setUri(topology.getUri());
+ for ( Provider provider : topology.getProviders() ) {
+ deploymentTopology.addProvider( getProvider(provider) );
+ }
+ for ( Service service : topology.getServices() ) {
+ deploymentTopology.addService( getService(service) );
+ }
+ for ( Application application : topology.getApplications() ) {
+ deploymentTopology.addApplication( getApplication(application) );
+ }
+ return deploymentTopology;
+ }
+
+ private static Provider getProvider(
+ org.apache.knox.gateway.topology.Provider provider) {
+ Provider providerResource = new Provider();
+ providerResource.setName(provider.getName());
+ providerResource.setEnabled(provider.isEnabled());
+ providerResource.setRole(provider.getRole());
+ Collection<org.apache.knox.gateway.topology.Param> paramsList = provider.getParamsList();
+ if (paramsList != null && !paramsList.isEmpty()) {
+ for ( org.apache.knox.gateway.topology.Param param : paramsList ) {
+ providerResource.getParams().add(getParam(param));
+ }
+ }
+ return providerResource;
+ }
+
+ private static org.apache.knox.gateway.topology.Provider getProvider(Provider provider) {
+ org.apache.knox.gateway.topology.Provider deploymentProvider = new org.apache.knox.gateway.topology.Provider();
+ deploymentProvider.setName(provider.getName());
+ deploymentProvider.setEnabled(provider.isEnabled());
+ deploymentProvider.setRole(provider.getRole());
+ for ( Param param : provider.getParams() ) {
+ deploymentProvider.addParam( getParam(param) );
+ }
+ return deploymentProvider;
+ }
+
+ private static Service getService(
+ org.apache.knox.gateway.topology.Service service) {
+ Service serviceResource = new Service();
+ serviceResource.setRole(service.getRole());
+ serviceResource.setName(service.getName());
+ Version version = service.getVersion();
+ if (version != null) {
+ serviceResource.setVersion(version.toString());
+ }
+ Collection<org.apache.knox.gateway.topology.Param> paramsList = service.getParamsList();
+ if (paramsList != null && !paramsList.isEmpty()) {
+ for ( org.apache.knox.gateway.topology.Param param : paramsList ) {
+ serviceResource.getParams().add(getParam(param));
+ }
+ }
+ for ( String url : service.getUrls() ) {
+ serviceResource.getUrls().add( url );
+ }
+ return serviceResource;
+ }
+
+ private static org.apache.knox.gateway.topology.Service getService(Service service) {
+ org.apache.knox.gateway.topology.Service deploymentService = new org.apache.knox.gateway.topology.Service();
+ deploymentService.setRole(service.getRole());
+ deploymentService.setName(service.getName());
+ if (service.getVersion() != null) {
+ deploymentService.setVersion(new Version(service.getVersion()));
+ }
+ for ( Param param : service.getParams() ) {
+ deploymentService.addParam( getParam(param) );
+ }
+ for ( String url : service.getUrls() ) {
+ deploymentService.addUrl( url );
+ }
+ return deploymentService;
+ }
+
+ private static Application getApplication(
+ org.apache.knox.gateway.topology.Application application) {
+ Application applicationResource = new Application();
+ applicationResource.setRole(application.getRole());
+ applicationResource.setName(application.getName());
+ Version version = application.getVersion();
+ if (version != null) {
+ applicationResource.setVersion(version.toString());
+ }
+ Collection<org.apache.knox.gateway.topology.Param> paramsList = application.getParamsList();
+ if (paramsList != null && !paramsList.isEmpty()) {
+ for ( org.apache.knox.gateway.topology.Param param : paramsList ) {
+ applicationResource.getParams().add(getParam(param));
+ }
+ }
+ for ( String url : application.getUrls() ) {
+ applicationResource.getUrls().add( url );
+ }
+ return applicationResource;
+ }
+
+ private static org.apache.knox.gateway.topology.Application getApplication(Application application) {
+ org.apache.knox.gateway.topology.Application applicationResource = new org.apache.knox.gateway.topology.Application();
+ applicationResource.setRole(application.getRole());
+ applicationResource.setName(application.getName());
+ if (application.getVersion() != null) {
+ applicationResource.setVersion(new Version(application.getVersion()));
+ }
+ for ( Param param : application.getParams() ) {
+ applicationResource.addParam( getParam(param) );
+ }
+ for ( String url : application.getUrls() ) {
+ applicationResource.getUrls().add( url );
+ }
+ return applicationResource;
+ }
+
+ private static Param getParam(org.apache.knox.gateway.topology.Param param) {
+ return new Param(param.getName(), param.getValue());
+ }
+
+ private static org.apache.knox.gateway.topology.Param getParam(Param param) {
+ return new org.apache.knox.gateway.topology.Param(param.getName(), param.getValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/Topology.java
----------------------------------------------------------------------
diff --cc gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/Topology.java
index 9c58ad3,0000000..2d2eab8
mode 100644,000000..100644
--- a/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/Topology.java
+++ b/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/beans/Topology.java
@@@ -1,108 -1,0 +1,119 @@@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.service.admin.beans;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+@XmlRootElement(name="topology")
+public class Topology {
+
+ @XmlElement
+ private URI uri;
+
+ @XmlElement
+ private String name;
+
+ @XmlElement
++ private String path;
++
++ @XmlElement
+ private long timestamp;
+
+ @XmlElement(name="provider")
+ @XmlElementWrapper(name="gateway")
+ public List<Provider> providers;
+
+ @XmlElement(name="service")
+ public List<Service> services;
+
+ @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 setPath( String defaultServicePath ) {
++ this.path = defaultServicePath;
++ }
++
++ public String getPath() {
++ return path;
++ }
++
+ public void setTimestamp( long timestamp ) {
+ this.timestamp = timestamp;
+ }
+
+ public List<Service> getServices() {
+ if (services == null) {
+ services = new ArrayList<>();
+ }
+ return services;
+ }
+
+ public List<Application> getApplications() {
+ if (applications == null) {
+ applications = new ArrayList<>();
+ }
+ return applications;
+ }
+
+ public List<Provider> getProviders() {
+ if (providers == null) {
+ providers = new ArrayList<>();
+ }
+ return providers;
+ }
+
+ public void setProviders(List<Provider> providers) {
+ this.providers = providers;
+ }
+
+ public void setServices(List<Service> services) {
+ this.services = services;
+ }
+
+ public void setApplications(List<Application> applications) {
+ this.applications = applications;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-spi/src/main/java/org/apache/knox/gateway/i18n/GatewaySpiMessages.java
----------------------------------------------------------------------
diff --cc gateway-spi/src/main/java/org/apache/knox/gateway/i18n/GatewaySpiMessages.java
index 243bac3,0000000..27a1905
mode 100644,000000..100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/i18n/GatewaySpiMessages.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/i18n/GatewaySpiMessages.java
@@@ -1,85 -1,0 +1,91 @@@
+/**
+ * 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.i18n;
+
+import org.apache.knox.gateway.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+import org.apache.knox.gateway.i18n.messages.StackTrace;
+
+@Messages(logger="org.apache.knox.gateway")
+public interface GatewaySpiMessages {
+
+ @Message(level = MessageLevel.ERROR, text = "Failed to load the internal principal mapping table: {0}" )
+ void failedToLoadPrincipalMappingTable( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to execute filter: {0}" )
+ void failedToExecuteFilter( @StackTrace( level = MessageLevel.DEBUG ) Throwable t );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to encrypt passphrase: {0}" )
+ void failedToEncryptPassphrase( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to generate secret key from password: {0}" )
+ void failedToGenerateKeyFromPassword( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to create keystore [filename={0}, type={1}]: {2}" )
+ void failedToCreateKeystore( String fileName, String keyStoreType, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to load keystore [filename={0}, type={1}]: {2}" )
+ void failedToLoadKeystore( String fileName, String keyStoreType, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to add credential: {1}" )
+ void failedToAddCredential( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message(level = MessageLevel.ERROR, text = "Failed to remove credential: {1}")
+ void failedToRemoveCredential(@StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to get credential: {1}" )
+ void failedToGetCredential(@StackTrace( level = MessageLevel.DEBUG ) Exception e);
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to persist master secret: {0}" )
+ void failedToPersistMasterSecret( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to encrypt master secret: {0}" )
+ void failedToEncryptMasterSecret( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to initialize master service from persistent master {0}: {1}" )
+ void failedToInitializeFromPersistentMaster( String masterFileName, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to add self signed certificate for Gateway {0}: {1}" )
+ void failedToAddSeflSignedCertForGateway( String alias, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+ @Message( level = MessageLevel.ERROR, text = "Failed to get key {0}: {1}" )
+ void failedToGetKey(String alias, @StackTrace( level = MessageLevel.DEBUG ) Exception e);
+
+ @Message( level = MessageLevel.DEBUG, text = "Loading from persistent master: {0}" )
+ void loadingFromPersistentMaster( String tag );
+
+ @Message( level = MessageLevel.DEBUG, text = "ALIAS: {0}" )
+ void printClusterAlias( String alias );
+
+ @Message( level = MessageLevel.DEBUG, text = "MASTER SERVICE == NULL: {0}" )
+ void printMasterServiceIsNull( boolean masterServiceIsNull );
+
+ @Message( level = MessageLevel.ERROR, text = "Gateway has failed to start. Unable to prompt user for master secret setup. Please consider using knoxcli.sh create-master" )
+ void unableToPromptForMasterUseKnoxCLI();
+
- @Message( level = MessageLevel.ERROR, text = "Error in generating certificate: {0}" )
- void failedToGenerateCertificate( @StackTrace( level = MessageLevel.ERROR ) Exception e );
++ @Message( level = MessageLevel.ERROR, text = "Error in generating certificate: {0}" )
++ void failedToGenerateCertificate( @StackTrace( level = MessageLevel.ERROR ) Exception e );
++
++ @Message(level = MessageLevel.ERROR, text = "Failed to read configuration: {0}")
++ void failedToReadConfigurationFile(final String filePath, @StackTrace(level = MessageLevel.DEBUG) Exception e );
++
++ @Message(level = MessageLevel.ERROR, text = "Invalid resource URI {0} : {1}")
++ void invalidResourceURI(final String uri, final String reason, @StackTrace(level = MessageLevel.DEBUG) Exception e );
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-spi/src/main/java/org/apache/knox/gateway/services/topology/TopologyService.java
----------------------------------------------------------------------
diff --cc gateway-spi/src/main/java/org/apache/knox/gateway/services/topology/TopologyService.java
index 820da73,0000000..3be3a4a
mode 100644,000000..100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/topology/TopologyService.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/topology/TopologyService.java
@@@ -1,50 -1,0 +1,63 @@@
+/**
+ * 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.services.topology;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.services.Service;
+import org.apache.knox.gateway.topology.Topology;
+import org.apache.knox.gateway.topology.TopologyListener;
+
++import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+
+public interface TopologyService extends Service {
+
- public void reloadTopologies();
++ void reloadTopologies();
+
- public void deployTopology(Topology t);
++ void deployTopology(Topology t);
+
- public void redeployTopologies(String topologyName);
++ void redeployTopologies(String topologyName);
+
- public void addTopologyChangeListener(TopologyListener listener);
++ void addTopologyChangeListener(TopologyListener listener);
+
- public void startMonitor() throws Exception;
++ void startMonitor() throws Exception;
+
- public void stopMonitor() throws Exception;
++ void stopMonitor() throws Exception;
+
- public Collection<Topology> getTopologies();
++ Collection<Topology> getTopologies();
+
- public void deleteTopology(Topology t);
++ boolean deployProviderConfiguration(String name, String content);
+
- public Map<String, List<String>> getServiceTestURLs(Topology t, GatewayConfig config);
++ Collection<File> getProviderConfigurations();
+
- }
++ boolean deployDescriptor(String name, String content);
++
++ Collection<File> getDescriptors();
++
++ void deleteTopology(Topology t);
++
++ boolean deleteDescriptor(String name);
++
++ boolean deleteProviderConfiguration(String name);
++
++ Map<String, List<String>> getServiceTestURLs(Topology t, GatewayConfig config);
++
++}
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-spi/src/main/java/org/apache/knox/gateway/topology/Topology.java
----------------------------------------------------------------------
diff --cc gateway-spi/src/main/java/org/apache/knox/gateway/topology/Topology.java
index 6eac50b,0000000..815c218
mode 100644,000000..100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/Topology.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/Topology.java
@@@ -1,142 -1,0 +1,151 @@@
+/**
+ * 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.topology;
+
+import org.apache.commons.collections.map.HashedMap;
+import org.apache.commons.collections.map.MultiKeyMap;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Topology {
+
+ private URI uri;
+ private String name;
++ private String defaultServicePath = null;
+ private long timestamp;
+ public List<Provider> providerList = new ArrayList<Provider>();
+ private Map<String,Map<String,Provider>> providerMap = new HashMap<>();
+ public List<Service> services = new ArrayList<Service>();
+ private MultiKeyMap serviceMap;
+ private List<Application> applications = new ArrayList<Application>();
+ private Map<String,Application> applicationMap = new HashMap<>();
+
+ public Topology() {
+ serviceMap = MultiKeyMap.decorate(new HashedMap());
+ }
+
+ 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 getDefaultServicePath() {
++ return defaultServicePath;
++ }
++
++ public void setDefaultServicePath(String servicePath) {
++ defaultServicePath = servicePath;
++ }
++
+ public Collection<Service> getServices() {
+ return services;
+ }
+
+ public Service getService( String role, String name, Version version) {
+ return (Service)serviceMap.get(role, name, version);
+ }
+
+ public void addService( Service service ) {
+ services.add( service );
+ serviceMap.put(service.getRole(), service.getName(), service.getVersion(), service);
+ }
+
+ public Collection<Application> getApplications() {
+ return applications;
+ }
+
+ private static String fixApplicationUrl( String url ) {
+ if( url == null ) {
+ url = "/";
+ }
+ if( !url.startsWith( "/" ) ) {
+ url = "/" + url;
+ }
+ return url;
+ }
+
+ public Application getApplication(String url) {
+ return applicationMap.get( fixApplicationUrl( url ) );
+ }
+
+ public void addApplication( Application application ) {
+ applications.add( application );
+ List<String> urls = application.getUrls();
+ if( urls == null || urls.isEmpty() ) {
+ applicationMap.put( fixApplicationUrl( application.getName() ), application );
+ } else {
+ for( String url : application.getUrls() ) {
+ applicationMap.put( fixApplicationUrl( url ), application );
+ }
+ }
+ }
+
+ public Collection<Provider> getProviders() {
+ return providerList;
+ }
+
+ public Provider getProvider( String role, String name ) {
+ Provider provider = null;
+ Map<String,Provider> nameMap = providerMap.get( role );
+ if( nameMap != null) {
+ if( name != null ) {
+ provider = nameMap.get( name );
+ }
+ else {
+ provider = (Provider) nameMap.values().toArray()[0];
+ }
+ }
+ return provider;
+ }
+
+ public void addProvider( Provider provider ) {
+ providerList.add( provider );
+ String role = provider.getRole();
+ Map<String,Provider> nameMap = providerMap.get( role );
+ if( nameMap == null ) {
+ nameMap = new HashMap<>();
+ providerMap.put( role, nameMap );
+ }
+ nameMap.put( provider.getName(), provider );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/c754cc06/gateway-spi/src/main/resources/org/apache/knox/gateway/topology/topology_binding-xml.xml
----------------------------------------------------------------------
diff --cc gateway-spi/src/main/resources/org/apache/knox/gateway/topology/topology_binding-xml.xml
index 9e9c26f,0000000..956387e
mode 100644,000000..100644
--- a/gateway-spi/src/main/resources/org/apache/knox/gateway/topology/topology_binding-xml.xml
+++ b/gateway-spi/src/main/resources/org/apache/knox/gateway/topology/topology_binding-xml.xml
@@@ -1,63 -1,0 +1,64 @@@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<xml-bindings
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
+ package-name="org.apache.knox.gateway.topology"
+ xml-mapping-metadata-complete="true">
+ <xml-schema
+ element-form-default="QUALIFIED"/>
+ <java-types>
+ <java-type name="Topology" xml-accessor-type="NONE">
- <xml-type prop-order="name providers services applications"/>
++ <xml-type prop-order="name defaultServicePath providers services applications"/>
+ <xml-root-element/>
+ <java-attributes>
+ <xml-element java-attribute="name" name="name"/>
++ <xml-element java-attribute="defaultServicePath" name="path"/>
+ <xml-elements java-attribute="providers">
+ <xml-element name="provider"/>
+ <xml-element-wrapper name="gateway"/>
+ </xml-elements>
+ <xml-element java-attribute="services" name="service"/>
+ <xml-element java-attribute="applications" name="application"/>
+ </java-attributes>
+ </java-type>
+ <java-type name="Provider" xml-accessor-type="NONE">
+ <java-attributes>
+ <xml-element java-attribute="name" name="name"/>
+ <xml-element java-attribute="enabled" name="enabled"/>
+ <xml-element java-attribute="role" name="role"/>
+ <xml-element java-attribute="paramsList" name="param"/>
+ </java-attributes>
+ </java-type>
+ <java-type name="Service" xml-accessor-type="NONE">
+ <java-attributes>
+ <xml-element java-attribute="name" name="name"/>
+ <xml-element java-attribute="role" name="role"/>
+ <xml-element java-attribute="urls" name="url"/>
+ <xml-element java-attribute="paramsList" name="param"/>
+ </java-attributes>
+ </java-type>
+ <java-type name="Application" xml-accessor-type="NONE"/>
+ <java-type name="Param" xml-accessor-type="NONE">
+ <java-attributes>
+ <xml-element java-attribute="name"/>
+ <xml-element java-attribute="value"/>
+ </java-attributes>
+ </java-type>
+ </java-types>
- </xml-bindings>
++</xml-bindings>