http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/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 a0035fc,0000000..9ecd7fc 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,657 -1,0 +1,674 @@@ +/** + * 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(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_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(SINGLE_TOPOLOGY_API_PATH) + public Topology uploadTopology(@PathParam("id") String id, Topology t) { ++ Topology result = null; + - GatewayServices gs = (GatewayServices) request.getServletContext() - .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); ++ 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)); ++ // Check for existing topology with the same name, to see if it had been generated ++ boolean existingGenerated = false; ++ for (org.apache.hadoop.gateway.topology.Topology existingTopology : ts.getTopologies()) { ++ if(existingTopology.getName().equals(id)) { ++ existingGenerated = existingTopology.isGenerated(); ++ break; ++ } ++ } ++ ++ // If a topology with the same ID exists, which had been generated, then DO NOT overwrite it because it will be ++ // out of sync with the source descriptor. Otherwise, deploy the updated version. ++ if (!existingGenerated) { ++ ts.deployTopology(BeanConverter.getTopology(t)); ++ result = getTopology(id); ++ } else { ++ log.disallowedOverwritingGeneratedTopology(id); ++ } + - return getTopology(id); ++ return result; + } + + @DELETE + @Produces(APPLICATION_JSON) + @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 uri = buildXForwardBaseURL(req); + + // Strip extra context + uri = uri.replace(req.getContextPath(), ""); + + // 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(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. + String pathInfo = req.getPathInfo(); + while(pathInfo.endsWith("/")) { + pathInfo = pathInfo.substring(0, pathInfo.length() - 1); + } + + href += pathInfo; + + if (id != null) { + href += "/" + id; + } + + return href; + } + + String buildHref(org.apache.knox.gateway.topology.Topology t, HttpServletRequest req) { + return buildHref(t.getName(), req); + } + + private SimpleTopology getSimpleTopology(org.apache.knox.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 + if(req.getHeader(X_Forwarded_Proto) != null){ + baseURL += req.getHeader(X_Forwarded_Proto) + "://"; + } else { + baseURL += req.getProtocol() + "://"; + } + + // 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 + 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; + 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 + 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. + baseURL += req.getServerName() + ":" + req.getHeader(X_Forwarded_Port); + } else { + // Resort to request members + baseURL += req.getServerName() + ":" + req.getLocalPort(); + } + + // 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/2c69152f/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 e8d6915,0000000..e916568 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,170 -1,0 +1,172 @@@ +/** + * 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()); ++ topologyResource.setGenerated(topology.isGenerated()); + 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()); ++ deploymentTopology.setGenerated(topology.isGenerated()); + 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/2c69152f/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 2d2eab8,0000000..e1a8279 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,119 -1,0 +1,130 @@@ +/** + * 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="generated") ++ private boolean isGenerated; ++ + @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 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 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/2c69152f/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/CustomDispatch.java ---------------------------------------------------------------------- diff --cc gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/CustomDispatch.java index 3fe81e8,0000000..ac82b39 mode 100644,000000..100644 --- a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/CustomDispatch.java +++ b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/CustomDispatch.java @@@ -1,80 -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.service.definition; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + +@XmlType(name = "dispatch") +public class CustomDispatch { + + private String contributorName; + + private String haContributorName; + + private String className; + + private String haClassName; + + private String httpClientFactory; + ++ private boolean useTwoWaySsl = false; ++ + @XmlAttribute(name = "contributor-name") + public String getContributorName() { + return contributorName; + } + + public void setContributorName(String contributorName) { + this.contributorName = contributorName; + } + + @XmlAttribute(name = "ha-contributor-name") + public String getHaContributorName() { + return haContributorName; + } + + public void setHaContributorName(String haContributorName) { + this.haContributorName = haContributorName; + } + + @XmlAttribute(name = "classname") + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + @XmlAttribute(name = "ha-classname") + public String getHaClassName() { + return haClassName; + } + + public void setHaClassName(String haContributorClassName) { + this.haClassName = haContributorClassName; + } + + @XmlAttribute(name = "http-client-factory") + public String getHttpClientFactory() { + return httpClientFactory; + } + + public void setHttpClientFactory(String httpClientFactory) { + this.httpClientFactory = httpClientFactory; + } ++ ++ @XmlAttribute(name = "use-two-way-ssl") ++ public boolean getUseTwoWaySsl() { ++ return useTwoWaySsl; ++ } ++ ++ public void setUseTwoWaySsl(boolean useTwoWaySsl) { ++ this.useTwoWaySsl = useTwoWaySsl; ++ } +} http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-shell-launcher/pom.xml ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-shell-release/pom.xml ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java ---------------------------------------------------------------------- diff --cc gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java index e822364,0000000..dcb7465 mode 100644,000000..100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultHttpClientFactory.java @@@ -1,233 -1,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.dispatch; + ++import java.io.IOException; ++import java.security.KeyStore; ++import java.security.Principal; ++import java.util.Collections; ++import java.util.Date; ++import java.util.List; ++ ++import javax.net.ssl.SSLContext; ++import javax.servlet.FilterConfig; ++ ++import org.apache.knox.gateway.services.security.AliasService; ++import org.apache.knox.gateway.services.security.AliasServiceException; ++import org.apache.knox.gateway.services.security.KeystoreService; ++import org.apache.knox.gateway.services.security.MasterService; +import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.services.GatewayServices; +import org.apache.knox.gateway.services.metrics.MetricsService; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolException; +import org.apache.http.auth.AuthSchemeProvider; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.Credentials; +import org.apache.http.client.CookieStore; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.RedirectStrategy; +import org.apache.http.client.config.AuthSchemes; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; ++import org.apache.http.conn.ssl.SSLConnectionSocketFactory; ++import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.DefaultConnectionReuseStrategy; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.protocol.HttpContext; ++import org.apache.http.ssl.SSLContexts; +import org.joda.time.Period; +import org.joda.time.format.PeriodFormatter; +import org.joda.time.format.PeriodFormatterBuilder; + - import javax.servlet.FilterConfig; - import java.io.IOException; - import java.security.Principal; - import java.util.Collections; - import java.util.Date; - import java.util.List; - +public class DefaultHttpClientFactory implements HttpClientFactory { + + @Override + public HttpClient createHttpClient(FilterConfig filterConfig) { + HttpClientBuilder builder = null; + GatewayConfig gatewayConfig = (GatewayConfig) filterConfig.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE); ++ GatewayServices services = (GatewayServices) filterConfig.getServletContext() ++ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + if (gatewayConfig != null && gatewayConfig.isMetricsEnabled()) { - GatewayServices services = (GatewayServices) filterConfig.getServletContext() - .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + MetricsService metricsService = services.getService(GatewayServices.METRICS_SERVICE); + builder = metricsService.getInstrumented(HttpClientBuilder.class); + } else { + builder = HttpClients.custom(); + } ++ if (Boolean.parseBoolean(filterConfig.getInitParameter("useTwoWaySsl"))) { ++ char[] keypass = null; ++ MasterService ms = services.getService("MasterService"); ++ AliasService as = services.getService(GatewayServices.ALIAS_SERVICE); ++ try { ++ keypass = as.getGatewayIdentityPassphrase(); ++ } catch (AliasServiceException e) { ++ // nop - default passphrase will be used ++ } ++ if (keypass == null) { ++ // there has been no alias created for the key - let's assume it is the same as the keystore password ++ keypass = ms.getMasterSecret(); ++ } ++ ++ KeystoreService ks = services.getService(GatewayServices.KEYSTORE_SERVICE); ++ final SSLContext sslcontext; ++ try { ++ KeyStore keystoreForGateway = ks.getKeystoreForGateway(); ++ sslcontext = SSLContexts.custom() ++ .loadTrustMaterial(keystoreForGateway, new TrustSelfSignedStrategy()) ++ .loadKeyMaterial(keystoreForGateway, keypass) ++ .build(); ++ } catch (Exception e) { ++ throw new IllegalArgumentException("Unable to create SSLContext", e); ++ } ++ builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext)); ++ } + if ( "true".equals(System.getProperty(GatewayConfig.HADOOP_KERBEROS_SECURED)) ) { + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, new UseJaasCredentials()); + + Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create() + .register(AuthSchemes.SPNEGO, new KnoxSpnegoAuthSchemeFactory(true)) + .build(); + + builder = builder.setDefaultAuthSchemeRegistry(authSchemeRegistry) + .setDefaultCookieStore(new HadoopAuthCookieStore()) + .setDefaultCredentialsProvider(credentialsProvider); + } else { + builder = builder.setDefaultCookieStore(new NoCookieStore()); + } + + builder.setKeepAliveStrategy( DefaultConnectionKeepAliveStrategy.INSTANCE ); + builder.setConnectionReuseStrategy( DefaultConnectionReuseStrategy.INSTANCE ); + builder.setRedirectStrategy( new NeverRedirectStrategy() ); + builder.setRetryHandler( new NeverRetryHandler() ); + + int maxConnections = getMaxConnections( filterConfig ); + builder.setMaxConnTotal( maxConnections ); + builder.setMaxConnPerRoute( maxConnections ); + + builder.setDefaultRequestConfig( getRequestConfig( filterConfig ) ); + + HttpClient client = builder.build(); + return client; + } + + private static RequestConfig getRequestConfig( FilterConfig config ) { + RequestConfig.Builder builder = RequestConfig.custom(); + int connectionTimeout = getConnectionTimeout( config ); + if ( connectionTimeout != -1 ) { + builder.setConnectTimeout( connectionTimeout ); + builder.setConnectionRequestTimeout( connectionTimeout ); + } + int socketTimeout = getSocketTimeout( config ); + if( socketTimeout != -1 ) { + builder.setSocketTimeout( socketTimeout ); + } + return builder.build(); + } + + private static class NoCookieStore implements CookieStore { + @Override + public void addCookie(Cookie cookie) { + //no op + } + + @Override + public List<Cookie> getCookies() { + return Collections.emptyList(); + } + + @Override + public boolean clearExpired(Date date) { + return true; + } + + @Override + public void clear() { + //no op + } + } + + private static class NeverRedirectStrategy implements RedirectStrategy { + @Override + public boolean isRedirected( HttpRequest request, HttpResponse response, HttpContext context ) + throws ProtocolException { + return false; + } + + @Override + public HttpUriRequest getRedirect( HttpRequest request, HttpResponse response, HttpContext context ) + throws ProtocolException { + return null; + } + } + + private static class NeverRetryHandler implements HttpRequestRetryHandler { + @Override + public boolean retryRequest( IOException exception, int executionCount, HttpContext context ) { + return false; + } + } + + private static class UseJaasCredentials implements Credentials { + + public String getPassword() { + return null; + } + + public Principal getUserPrincipal() { + return null; + } + + } + + private int getMaxConnections( FilterConfig filterConfig ) { + int maxConnections = 32; + GatewayConfig config = + (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE ); + if( config != null ) { + maxConnections = config.getHttpClientMaxConnections(); + } + String str = filterConfig.getInitParameter( "httpclient.maxConnections" ); + if( str != null ) { + try { + maxConnections = Integer.parseInt( str ); + } catch ( NumberFormatException e ) { + // Ignore it and use the default. + } + } + return maxConnections; + } + + private static int getConnectionTimeout( FilterConfig filterConfig ) { + int timeout = -1; + GatewayConfig globalConfig = + (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE ); + if( globalConfig != null ) { + timeout = globalConfig.getHttpClientConnectionTimeout(); + } + String str = filterConfig.getInitParameter( "httpclient.connectionTimeout" ); + if( str != null ) { + try { + timeout = (int)parseTimeout( str ); + } catch ( Exception e ) { + // Ignore it and use the default. + } + } + return timeout; + } + + private static int getSocketTimeout( FilterConfig filterConfig ) { + int timeout = -1; + GatewayConfig globalConfig = + (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE ); + if( globalConfig != null ) { + timeout = globalConfig.getHttpClientSocketTimeout(); + } + String str = filterConfig.getInitParameter( "httpclient.socketTimeout" ); + if( str != null ) { + try { + timeout = (int)parseTimeout( str ); + } catch ( Exception e ) { + // Ignore it and use the default. + } + } + return timeout; + } + + private static long parseTimeout( String s ) { + PeriodFormatter f = new PeriodFormatterBuilder() + .appendMinutes().appendSuffix("m"," min") + .appendSeconds().appendSuffix("s"," sec") + .appendMillis().toFormatter(); + Period p = Period.parse( s, f ); + return p.toStandardDuration().getMillis(); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/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 27a1905,0000000..42d69d9 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,91 -1,0 +1,94 @@@ +/** + * 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 = "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 ); + ++ @Message( level = MessageLevel.ERROR, text = "Topology {0} cannot be manually overwritten because it was generated from a simple descriptor." ) ++ void disallowedOverwritingGeneratedTopology(final String topologyName); ++ +} http://git-wip-us.apache.org/repos/asf/knox/blob/2c69152f/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 815c218,0000000..e46197d 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,151 -1,0 +1,160 @@@ +/** + * 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; ++ private boolean isGenerated; + 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 void setGenerated(boolean isGenerated) { ++ this.isGenerated = isGenerated; ++ } ++ ++ public boolean isGenerated() { ++ return isGenerated; ++ } ++ + 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 ); + } + +}
