Repository: knox
Updated Branches:
  refs/heads/master 5b57a5151 -> cd3367599


http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
----------------------------------------------------------------------
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
index f10f97b..b53d3b8 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayMessages.java
@@ -565,6 +565,9 @@ public interface GatewayMessages {
   @Message( level = MessageLevel.INFO, text = "Remote configuration monitor 
deleted {0} configuration file {1} based on remote change." )
   void deletedRemoteConfigFile(final String type, final String configFileName);
 
+  @Message( level = MessageLevel.ERROR, text = "Failed to delete remote {0} 
file {1}." )
+  void failedToDeletedRemoteConfigFile(final String type, final String 
configFileName);
+
   @Message( level = MessageLevel.ERROR, text = "An error occurred while 
processing {0} : {1}" )
   void simpleDescriptorHandlingError(final String simpleDesc,
                                      @StackTrace(level = MessageLevel.DEBUG) 
Exception e);

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-server/src/main/java/org/apache/knox/gateway/services/topology/impl/DefaultTopologyService.java
----------------------------------------------------------------------
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/topology/impl/DefaultTopologyService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/topology/impl/DefaultTopologyService.java
index 5985d5f..011975a 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/topology/impl/DefaultTopologyService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/topology/impl/DefaultTopologyService.java
@@ -40,6 +40,7 @@ import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 import org.apache.knox.gateway.service.definition.ServiceDefinition;
 import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.ServiceLifecycleException;
+import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.topology.TopologyService;
 import org.apache.knox.gateway.topology.ClusterConfigurationMonitorService;
@@ -426,7 +427,22 @@ public class DefaultTopologyService
 
   @Override
   public boolean deployProviderConfiguration(String name, String content) {
-    return writeConfig(sharedProvidersDirectory, name, content);
+    boolean result;
+
+    // Whether the remote configuration registry is being employed or not, 
write the file locally
+    result =  writeConfig(sharedProvidersDirectory, name, content);
+
+    // If the remote configuration registry is being employed, persist it 
there also
+    if (remoteMonitor != null) {
+      RemoteConfigurationRegistryClient client = remoteMonitor.getClient();
+      if (client != null) {
+        String entryPath = "/knox/config/shared-providers/" + name;
+        client.createEntry(entryPath, content);
+        result = (client.getEntryData(entryPath) != null);
+      }
+    }
+
+    return result;
   }
 
   @Override
@@ -444,16 +460,29 @@ public class DefaultTopologyService
   public boolean deleteProviderConfiguration(String name) {
     boolean result = false;
 
+    // Determine if the file exists, and if so, if there are any descriptors 
referencing it
+    boolean hasReferences = false;
     File providerConfig = getExistingFile(sharedProvidersDirectory, name);
     if (providerConfig != null) {
       List<String> references = 
descriptorsMonitor.getReferencingDescriptors(providerConfig.getAbsolutePath());
-      if (references.isEmpty()) {
+      hasReferences = !references.isEmpty();
+    } else {
+      result = true; // If it already does NOT exist, then the delete 
effectively succeeded
+    }
+
+    // If the local file does not exist, or it does exist and there are NOT 
any referencing descriptors
+    if (providerConfig == null || !hasReferences) {
+
+      // If the remote config monitor is configured, attempt to delete the 
provider configuration from the remote
+      // registry, even if it does not exist locally.
+      deleteRemoteEntry("/knox/config/shared-providers", name);
+
+      if (providerConfig != null) {
+        // Whether the remote configuration registry is being employed or not, 
delete the local file if it exists
         result = providerConfig.delete();
-      } else {
-        
log.preventedDeletionOfSharedProviderConfiguration(providerConfig.getAbsolutePath());
       }
     } else {
-      result = true; // If it already does NOT exist, then the delete 
effectively succeeded
+      
log.preventedDeletionOfSharedProviderConfiguration(providerConfig.getAbsolutePath());
     }
 
     return result;
@@ -461,7 +490,22 @@ public class DefaultTopologyService
 
   @Override
   public boolean deployDescriptor(String name, String content) {
-    return writeConfig(descriptorsDirectory, name, content);
+    boolean result;
+
+    // Whether the remote configuration registry is being employed or not, 
write the file locally
+    result = writeConfig(descriptorsDirectory, name, content);
+
+    // If the remote configuration registry is being employed, persist it 
there also
+    if (remoteMonitor != null) {
+      RemoteConfigurationRegistryClient client = remoteMonitor.getClient();
+      if (client != null) {
+        String entryPath = "/knox/config/descriptors/" + name;
+        client.createEntry(entryPath, content);
+        result = (client.getEntryData(entryPath) != null);
+      }
+    }
+
+    return result;
   }
 
   @Override
@@ -477,8 +521,16 @@ public class DefaultTopologyService
 
   @Override
   public boolean deleteDescriptor(String name) {
+    boolean result;
+
+    // If the remote config monitor is configured, delete the descriptor from 
the remote registry
+    deleteRemoteEntry("/knox/config/descriptors", name);
+
+    // Whether the remote configuration registry is being employed or not, 
delete the local file
     File descriptor = getExistingFile(descriptorsDirectory, name);
-    return (descriptor == null) || descriptor.delete();
+    result = (descriptor == null) || descriptor.delete();
+
+    return result;
   }
 
   @Override
@@ -642,6 +694,38 @@ public class DefaultTopologyService
   }
 
   /**
+   * Delete the entry in the remote configuration registry, which matches the 
specified resource name.
+   *
+   * @param entryParent The remote registry path in which the entry exists.
+   * @param name        The name of the entry (typically without any file 
extension).
+   *
+   * @return true, if the entry is deleted, or did not exist; otherwise, false.
+   */
+  private boolean deleteRemoteEntry(String entryParent, String name) {
+    boolean result = true;
+
+    if (remoteMonitor != null) {
+      RemoteConfigurationRegistryClient client = remoteMonitor.getClient();
+      if (client != null) {
+        List<String> existingProviderConfigs = 
client.listChildEntries(entryParent);
+        for (String entryName : existingProviderConfigs) {
+          if (FilenameUtils.getBaseName(entryName).equals(name)) {
+            String entryPath = entryParent + "/" + entryName;
+            client.deleteEntry(entryPath);
+            result = !client.entryExists(entryPath);
+            if (!result) {
+              log.failedToDeletedRemoteConfigFile("descriptor", name);
+            }
+            break;
+          }
+        }
+      }
+    }
+
+    return result;
+  }
+
+  /**
    * Utility method for listing the files in the specified directory.
    * This method is "nicer" than the File#listFiles() because it will not 
return null.
    *

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-server/src/main/java/org/apache/knox/gateway/topology/monitor/DefaultRemoteConfigurationMonitor.java
----------------------------------------------------------------------
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/topology/monitor/DefaultRemoteConfigurationMonitor.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/topology/monitor/DefaultRemoteConfigurationMonitor.java
index 37d1ca6..6db3952 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/topology/monitor/DefaultRemoteConfigurationMonitor.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/topology/monitor/DefaultRemoteConfigurationMonitor.java
@@ -97,6 +97,11 @@ class DefaultRemoteConfigurationMonitor implements 
RemoteConfigurationMonitor {
     }
 
     @Override
+    public RemoteConfigurationRegistryClient getClient() {
+        return client;
+    }
+
+    @Override
     public void start() throws Exception {
         if (client == null) {
             throw new IllegalStateException("Failed to acquire a remote 
configuration registry client.");

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
----------------------------------------------------------------------
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java 
b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
index a987433..6524ca0 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/util/KnoxCLI.java
@@ -1924,8 +1924,10 @@ public class KnoxCLI extends Configured implements Tool {
       if (client != null) {
         out.println("Provider Configurations (@" + client.getAddress() + ")");
         List<String> entries = client.listChildEntries(PROVIDER_CONFIG_ENTRY);
-        for (String entry : entries) {
-          out.println(entry);
+        if (entries != null) {
+          for (String entry : entries) {
+            out.println(entry);
+          }
         }
         out.println();
       }
@@ -1948,8 +1950,10 @@ public class KnoxCLI extends Configured implements Tool {
       if (client != null) {
         out.println("Descriptors (@" + client.getAddress() + ")");
         List<String> entries = client.listChildEntries(DESCRIPTORS_ENTRY);
-        for (String entry : entries) {
-          out.println(entry);
+        if (entries != null) {
+          for (String entry : entries) {
+            out.println(entry);
+          }
         }
         out.println();
       }

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java
----------------------------------------------------------------------
diff --git 
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
index 823f9ad..3a39ce2 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
@@ -37,6 +37,8 @@ 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.HttpHeaders;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
@@ -50,7 +52,9 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static javax.ws.rs.core.MediaType.APPLICATION_XML;
@@ -67,6 +71,7 @@ public class TopologiesResource {
 
   private static final String XML_EXT  = ".xml";
   private static final String JSON_EXT = ".json";
+  private static final String YAML_EXT = ".yml";
 
   private static final String TOPOLOGIES_API_PATH    = "topologies";
   private static final String SINGLE_TOPOLOGY_API_PATH = TOPOLOGIES_API_PATH + 
"/{id}";
@@ -77,6 +82,13 @@ public class TopologiesResource {
 
   private static GatewaySpiMessages log = 
MessagesFactory.get(GatewaySpiMessages.class);
 
+  private static final Map<MediaType, String> mediaTypeFileExtensions = new 
HashMap<>();
+  static {
+    mediaTypeFileExtensions.put(MediaType.APPLICATION_XML_TYPE, XML_EXT);
+    mediaTypeFileExtensions.put(MediaType.APPLICATION_JSON_TYPE, JSON_EXT);
+    mediaTypeFileExtensions.put(MediaType.TEXT_PLAIN_TYPE, YAML_EXT);
+  }
+
   @Context
   private HttpServletRequest request;
 
@@ -288,9 +300,9 @@ public class TopologiesResource {
 
 
   @PUT
-  @Consumes({APPLICATION_XML})
+  @Consumes({APPLICATION_XML, APPLICATION_JSON, TEXT_PLAIN})
   @Path(SINGLE_PROVIDERCONFIG_API_PATH)
-  public Response uploadProviderConfiguration(@PathParam("name") String name, 
String content) {
+  public Response uploadProviderConfiguration(@PathParam("name") String name, 
@Context HttpHeaders headers, String content) {
     Response response = null;
 
     GatewayServices gs =
@@ -298,14 +310,18 @@ public class TopologiesResource {
 
     TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
 
-    boolean isUpdate = configFileExists(ts.getProviderConfigurations(), name);
+    File existing = getExistingConfigFile(ts.getProviderConfigurations(), 
name);
+    boolean isUpdate = (existing != null);
+
+    // If it's an update, then use the matching existing filename; otherwise, 
use the media type to determine the file
+    // extension.
+    String filename = isUpdate ? existing.getName() : 
getFileNameForResource(name, headers);
 
-    String filename = name.endsWith(XML_EXT) ? name : name + XML_EXT;
     if (ts.deployProviderConfiguration(filename, content)) {
       try {
         if (isUpdate) {
           response = Response.noContent().build();
-        } else{
+        } else {
           response = created(new URI(buildHref(request))).build();
         }
       } catch (URISyntaxException e) {
@@ -317,23 +333,10 @@ public class TopologiesResource {
     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})
+  @Consumes({APPLICATION_JSON, TEXT_PLAIN})
   @Path(SINGLE_DESCRIPTOR_API_PATH)
-  public Response uploadSimpleDescriptor(@PathParam("name") String name, 
String content) {
+  public Response uploadSimpleDescriptor(@PathParam("name") String name, 
@Context HttpHeaders headers, String content) {
     Response response = null;
 
     GatewayServices gs =
@@ -341,9 +344,13 @@ public class TopologiesResource {
 
     TopologyService ts = gs.getService(GatewayServices.TOPOLOGY_SERVICE);
 
-    boolean isUpdate = configFileExists(ts.getDescriptors(), name);
+    File existing = getExistingConfigFile(ts.getDescriptors(), name);
+    boolean isUpdate = (existing != null);
+
+    // If it's an update, then use the matching existing filename; otherwise, 
use the media type to determine the file
+    // extension.
+    String filename = isUpdate ? existing.getName() : 
getFileNameForResource(name, headers);
 
-    String filename = name.endsWith(JSON_EXT) ? name : name + JSON_EXT;
     if (ts.deployDescriptor(filename, content)) {
       try {
         if (isUpdate) {
@@ -426,6 +433,43 @@ public class TopologiesResource {
   }
 
 
+  private String getFileNameForResource(String resourceName, HttpHeaders 
headers) {
+    String filename;
+    String extension = FilenameUtils.getExtension(resourceName);
+    if (extension != null && !extension.isEmpty()) {
+      filename = resourceName;
+    } else {
+      extension = getExtensionForMediaType(headers.getMediaType());
+      filename = (extension != null) ? (resourceName + extension) : 
(resourceName + JSON_EXT);
+    }
+    return filename;
+  }
+
+  private String getExtensionForMediaType(MediaType type) {
+    String extension = null;
+
+    for (MediaType key : mediaTypeFileExtensions.keySet()) {
+      if (type.isCompatible(key)) {
+        extension = mediaTypeFileExtensions.get(key);
+        break;
+      }
+    }
+
+    return extension;
+  }
+
+  private File getExistingConfigFile(Collection<File> existing, String 
candidateName) {
+    File result = null;
+    for (File exists : existing) {
+      if (FilenameUtils.getBaseName(exists.getName()).equals(candidateName)) {
+        result = exists;
+        break;
+      }
+    }
+    return result;
+  }
+
+
   private static class TopologyComparator implements 
Comparator<SimpleTopology> {
     @Override
     public int compare(SimpleTopology t1, SimpleTopology t2) {

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java
----------------------------------------------------------------------
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java
index 0ce1513..c9f3394 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/topology/monitor/RemoteConfigurationMonitor.java
@@ -16,9 +16,14 @@
  */
 package org.apache.knox.gateway.topology.monitor;
 
+import 
org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
+
 public interface RemoteConfigurationMonitor {
 
     void start() throws Exception;
 
     void stop() throws Exception;
+
+    RemoteConfigurationRegistryClient getClient();
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/cd336759/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java
----------------------------------------------------------------------
diff --git 
a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java
 
b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java
index c5d5fba..0db0121 100644
--- 
a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java
+++ 
b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java
@@ -1000,15 +1000,6 @@ public class GatewayAdminTopologyFuncTest {
 
     XMLTag newProviderConfigXML = createProviderConfiguration();
 
-    // Attempt to PUT a provider config with an INCORRECT Content-type header
-    given()
-        .auth().preemptive().basic(username, password)
-        .header("Content-type", MediaType.APPLICATION_JSON)
-        .body(newProviderConfigXML.toBytes("utf-8"))
-        .then()
-        .statusCode(HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE)
-        .when().put(serviceUrl + "/" + newProviderConfigName);
-
     // Attempt to PUT a provider config with the CORRECT Content-type header
     given()
         .auth().preemptive().basic(username, password)

Reply via email to