ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rle...@apache.org
Subject [2/2] ambari git commit: AMBARI-22481. Make Ambari LDAP configuration API consistent with existing API (rlevas)
Date Thu, 30 Nov 2017 17:04:27 GMT
AMBARI-22481. Make Ambari LDAP configuration API consistent with existing API (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4240f849
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4240f849
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4240f849

Branch: refs/heads/trunk
Commit: 4240f8496175bf9fb369b9411e71ad1127e356ad
Parents: c3150a4
Author: Robert Levas <rlevas@hortonworks.com>
Authored: Thu Nov 30 12:04:12 2017 -0500
Committer: Robert Levas <rlevas@hortonworks.com>
Committed: Thu Nov 30 12:04:12 2017 -0500

----------------------------------------------------------------------
 .../server/api/handlers/CreateHandler.java      |   8 +-
 .../server/api/handlers/UpdateHandler.java      |   8 +-
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +-
 ...ootServiceComponentConfigurationService.java |  15 ++
 .../api/services/ldap/AmbariConfiguration.java  |  46 ----
 .../api/services/ldap/LdapConfigOperation.java  |  43 ----
 .../services/ldap/LdapConfigurationRequest.java |  49 ----
 .../services/ldap/LdapConfigurationService.java | 185 --------------
 .../api/services/ldap/LdapRequestInfo.java      |  61 -----
 .../services/serializers/JsonSerializer.java    |  38 ++-
 .../commands/StackAdvisorCommand.java           |  14 +-
 .../AmbariServerConfigurationCategory.java      |  69 ++++++
 .../AmbariServerConfigurationHandler.java       | 110 +++++++++
 .../AmbariServerLDAPConfigurationHandler.java   | 172 +++++++++++++
 .../internal/OperationStatusMetaData.java       |  90 +++++++
 ...ootServiceComponentConfigurationHandler.java | 114 +++++++++
 ...iceComponentConfigurationHandlerFactory.java |  54 +++++
 ...eComponentConfigurationResourceProvider.java | 243 ++++++++-----------
 .../apache/ambari/server/ldap/LdapModule.java   |   4 -
 .../ldap/domain/AmbariLdapConfigKeys.java       |  83 -------
 .../ldap/domain/AmbariLdapConfiguration.java    |  85 +++----
 .../domain/AmbariLdapConfigurationFactory.java  |  34 ---
 .../domain/AmbariLdapConfigurationKeys.java     |  83 +++++++
 .../AmbariLdapConfigurationProvider.java        |  19 +-
 .../server/ldap/service/AmbariLdapFacade.java   |   4 +-
 .../ambari/server/ldap/service/LdapFacade.java  |   9 +-
 .../DefaultLdapAttributeDetectionService.java   |   8 +-
 .../ads/DefaultLdapConfigurationService.java    |   4 +-
 .../ads/detectors/GroupMemberAttrDetector.java  |   4 +-
 .../ads/detectors/GroupNameAttrDetector.java    |   7 +-
 .../ads/detectors/GroupObjectClassDetector.java |   8 +-
 .../detectors/UserGroupMemberAttrDetector.java  |   5 +-
 .../ads/detectors/UserNameAttrDetector.java     |   4 +-
 .../ads/detectors/UserObjectClassDetector.java  |   4 +-
 .../commands/StackAdvisorCommandTest.java       |   4 +-
 ...ponentConfigurationResourceProviderTest.java | 214 +++++++++++++---
 .../server/ldap/LdapModuleFunctionalTest.java   |  49 ++--
 .../TestAmbariLdapConfigurationFactory.java     |  29 ---
 .../ldap/service/AmbariLdapFacadeTest.java      |  36 ++-
 ...efaultLdapAttributeDetectionServiceTest.java |  24 +-
 .../DefaultLdapConfigurationServiceTest.java    |  31 ++-
 41 files changed, 1184 insertions(+), 891 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
index b614c5e..484547a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/CreateHandler.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.RequestStatus;
 import org.apache.ambari.server.controller.spi.RequestStatusMetaData;
@@ -94,6 +95,11 @@ public class CreateHandler extends BaseManagementHandler {
       return null;
     }
 
-    throw new UnsupportedOperationException();
+    if (requestStatusMetaData.getClass() == OperationStatusMetaData.class) {
+      return (OperationStatusMetaData) requestStatusMetaData;
+    } else {
+      throw new IllegalArgumentException(String.format("RequestStatusDetails is of an expected type: %s",
+          requestStatusMetaData.getClass().getName()));
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
index 2f1af51..c578cb9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/UpdateHandler.java
@@ -24,6 +24,7 @@ import org.apache.ambari.server.api.services.Result;
 import org.apache.ambari.server.api.services.ResultImpl;
 import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.RequestStatus;
@@ -79,6 +80,11 @@ public class UpdateHandler extends BaseManagementHandler {
       return null;
     }
 
-    throw new UnsupportedOperationException();
+    if (requestStatusMetaData.getClass() == OperationStatusMetaData.class) {
+      return (OperationStatusMetaData) requestStatusMetaData;
+    } else {
+      throw new IllegalArgumentException(String.format("RequestStatusDetails is of an expected type: %s",
+          requestStatusMetaData.getClass().getName()));
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index fecaedc..47da19b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.api.query.QueryImpl;
+import org.apache.ambari.server.api.services.RootServiceComponentConfigurationService;
 import org.apache.ambari.server.controller.internal.ClusterKerberosDescriptorResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
@@ -239,7 +240,8 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
 
       case RootServiceComponentConfiguration:
         resourceDefinition = new SimpleResourceDefinition(Resource.Type.RootServiceComponentConfiguration,
-            "configuration", "configurations");
+            "configuration", "configurations",
+            null, RootServiceComponentConfigurationService.DIRECTIVES_MAP);
         break;
 
       case RootServiceHostComponent:

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
index c7c37a6..a6be143 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceComponentConfigurationService.java
@@ -34,6 +34,7 @@ package org.apache.ambari.server.api.services;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -48,10 +49,14 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.ambari.server.api.resources.BaseResourceDefinition;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.http.HttpStatus;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -91,6 +96,16 @@ public class RootServiceComponentConfigurationService extends BaseService {
   private static final String REQUEST_TYPE =
       "org.apache.ambari.server.api.services.RootServiceComponentConfigurationRequestSwagger";
 
+  public static final String DIRECTIVE_OPERATION = "op";
+
+  private static final Set<String> DIRECTIVES = Sets.newHashSet(DIRECTIVE_OPERATION);
+
+  public static final Map<BaseResourceDefinition.DirectiveType, Set<String>> DIRECTIVES_MAP =
+      ImmutableMap.<BaseResourceDefinition.DirectiveType, Set<String>>builder()
+          .put(BaseResourceDefinition.DirectiveType.CREATE, DIRECTIVES)
+          .put(BaseResourceDefinition.DirectiveType.UPDATE, DIRECTIVES)
+          .build();
+
   private final String serviceName;
   private final String componentName;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
deleted file mode 100644
index 7bac65e..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/AmbariConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.api.services.ldap;
-
-import java.util.Map;
-
-/**
- * Domain POJO representing generic ambari configuration data.
- */
-public class AmbariConfiguration {
-
-  /**
-   * The type of the configuration,  eg.: ldap-configuration
-   */
-  private String type;
-
-  private Map<String, String> properties = null;
-
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  public Map<String, String> getProperties() {
-    return properties;
-  }
-
-  public void setProperties(Map<String, String> data) {
-    this.properties = data;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
deleted file mode 100644
index 478d4ff..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigOperation.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.api.services.ldap;
-
-/**
- * Enumeration for supported operations related to LDAP configuration.
- */
-public enum LdapConfigOperation {
-  TEST_CONNECTION("test-connection"),
-  TEST_ATTRIBUTES("test-attributes"),
-  DETECT_ATTRIBUTES("detect-attributes");
-
-  private String actionStr;
-
-  LdapConfigOperation(String actionStr) {
-    this.actionStr = actionStr;
-  }
-
-  public static LdapConfigOperation fromAction(String action) {
-    for (LdapConfigOperation val : LdapConfigOperation.values()) {
-      if (val.action().equals(action)) {
-        return val;
-      }
-    }
-    throw new IllegalStateException("Action [ " + action + " ] is not supported");
-  }
-
-  public String action() {
-    return this.actionStr;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
deleted file mode 100644
index 0e065e5..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationRequest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.api.services.ldap;
-
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * Request object wrapping information for LDAP configuration related request calls.
- */
-public class LdapConfigurationRequest {
-
-  @SerializedName("Configuration")
-  private AmbariConfiguration ambariConfiguration;
-
-  @SerializedName("RequestInfo")
-  private LdapRequestInfo requestInfo;
-
-  public LdapConfigurationRequest() {
-  }
-
-  public AmbariConfiguration getAmbariConfiguration() {
-    return ambariConfiguration;
-  }
-
-  public void setAmbariConfiguration(AmbariConfiguration ambariConfiguration) {
-    this.ambariConfiguration = ambariConfiguration;
-  }
-
-  public LdapRequestInfo getRequestInfo() {
-    return requestInfo;
-  }
-
-  public void setRequestInfo(LdapRequestInfo requestInfo) {
-    this.requestInfo = requestInfo;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
deleted file mode 100644
index 22784cd..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapConfigurationService.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.api.services.ldap;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.ambari.annotations.ApiIgnore;
-import org.apache.ambari.server.StaticallyInject;
-import org.apache.ambari.server.api.services.BaseService;
-import org.apache.ambari.server.api.services.Result;
-import org.apache.ambari.server.api.services.ResultImpl;
-import org.apache.ambari.server.api.services.ResultStatus;
-import org.apache.ambari.server.controller.internal.ResourceImpl;
-import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
-import org.apache.ambari.server.ldap.service.LdapFacade;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
-import org.apache.ambari.server.security.authorization.AuthorizationHelper;
-import org.apache.ambari.server.security.authorization.ResourceType;
-import org.apache.ambari.server.security.authorization.RoleAuthorization;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.core.Authentication;
-
-import com.google.common.collect.Sets;
-
-/**
- * Endpoint designated to LDAP specific operations.
- */
-@StaticallyInject
-@Path("/ldapconfigs/")
-public class LdapConfigurationService extends BaseService {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(LdapConfigurationService.class);
-
-  @Inject
-  private static LdapFacade ldapFacade;
-
-  @Inject
-  private static AmbariLdapConfigurationFactory ambariLdapConfigurationFactory;
-
-
-  @POST
-  @ApiIgnore // until documented
-  @Path("/validate")
-  @Consumes(MediaType.APPLICATION_JSON)
-  @Produces(MediaType.APPLICATION_JSON)
-  public Response validateConfiguration(LdapConfigurationRequest ldapConfigurationRequest) {
-
-    // check if the user is authorized to perform the operation
-    authorize();
-
-    Set<String> groups = Sets.newHashSet();
-    Object responseEntity = null;
-
-    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
-    try {
-
-      validateRequest(ldapConfigurationRequest);
-
-      AmbariLdapConfiguration ambariLdapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(
-        ldapConfigurationRequest.getAmbariConfiguration().getProperties());
-
-      LdapConfigOperation action = LdapConfigOperation.fromAction(ldapConfigurationRequest.getRequestInfo().getAction());
-      switch (action) {
-
-        case TEST_CONNECTION:
-
-          LOGGER.info("Testing connection to the LDAP server ...");
-          ldapFacade.checkConnection(ambariLdapConfiguration);
-
-          break;
-        case TEST_ATTRIBUTES:
-
-          LOGGER.info("Testing LDAP attributes ....");
-          groups = ldapFacade.checkLdapAttributes(ldapConfigurationRequest.getRequestInfo().getParameters(), ambariLdapConfiguration);
-          responseEntity = groups;
-
-          break;
-        case DETECT_ATTRIBUTES:
-
-          LOGGER.info("Detecting LDAP attributes ...");
-          ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
-          responseEntity = ambariLdapConfiguration;
-
-          break;
-        default:
-          LOGGER.warn("No action provided ...");
-          throw new IllegalArgumentException("No request action provided");
-      }
-
-    } catch (Exception e) {
-      result.setResultStatus(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, e));
-      responseEntity = e.getMessage();
-    }
-
-    return Response.status(result.getStatus().getStatusCode()).entity(responseEntity).build();
-  }
-
-  private void setResult(Set<String> groups, Result result) {
-    Resource resource = new ResourceImpl(Resource.Type.RootServiceComponentConfiguration);
-    resource.setProperty("groups", groups);
-    result.getResultTree().addChild(resource, "payload");
-  }
-
-  private void validateRequest(LdapConfigurationRequest ldapConfigurationRequest) {
-    String errMsg;
-
-    if (null == ldapConfigurationRequest) {
-      errMsg = "No ldap configuraiton request provided";
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapConfigurationRequest.getRequestInfo()) {
-      errMsg = String.format("No request information provided. Request: [%s]", ldapConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-
-    if (null == ldapConfigurationRequest.getAmbariConfiguration()
-      || ldapConfigurationRequest.getAmbariConfiguration().getProperties() != null) {
-      errMsg = String.format("No / Invalid configuration data provided. Request: [%s]", ldapConfigurationRequest);
-      LOGGER.error(errMsg);
-      throw new IllegalArgumentException(errMsg);
-    }
-  }
-
-  private void authorize() {
-    try {
-      Authentication authentication = AuthorizationHelper.getAuthentication();
-
-      if (authentication == null || !authentication.isAuthenticated()) {
-        throw new AuthorizationException("Authentication data is not available, authorization to perform the requested operation is not granted");
-      }
-
-      if (!AuthorizationHelper.isAuthorized(authentication, ResourceType.AMBARI, null, requiredAuthorizations())) {
-        throw new AuthorizationException("The authenticated user does not have the appropriate authorizations to create the requested resource(s)");
-      }
-    } catch (AuthorizationException e) {
-      LOGGER.error("Unauthorized operation.", e);
-      throw new IllegalArgumentException("User is not authorized to perform the operation", e);
-    }
-
-  }
-
-  private Set<RoleAuthorization> requiredAuthorizations() {
-    return Sets.newHashSet(RoleAuthorization.AMBARI_MANAGE_CONFIGURATION);
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
deleted file mode 100644
index eeecfee..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ldap/LdapRequestInfo.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.api.services.ldap;
-
-import java.util.Map;
-
-import org.apache.ambari.server.controller.RequestPostRequest;
-
-/**
- * Bean holding LDAP request specific request information.
- */
-public class LdapRequestInfo implements RequestPostRequest.RequestInfo {
-
-  // no-arg costructor facilitating JSON serialization
-  public LdapRequestInfo() {
-  }
-
-  private String action;
-
-  private Map<String, Object> parameters;
-
-  @Override
-  public String getAction() {
-    return action;
-  }
-
-  public void setAction(String action) {
-    this.action = action;
-  }
-
-  public void setParameters(Map<String, Object> parameters) {
-    this.parameters = parameters;
-  }
-
-  @Override
-  public String getCommand() {
-    return null;
-  }
-
-  @Override
-  public RequestPostRequest.OperationLevel getOperationLevel() {
-    return null;
-  }
-
-  @Override
-  public Map<String, Object> getParameters() {
-    return parameters;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
index 0604d2b..a045d74 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
@@ -31,6 +31,7 @@ import org.apache.ambari.server.api.services.ResultMetadata;
 import org.apache.ambari.server.api.services.ResultStatus;
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.api.util.TreeNodeImpl;
+import org.apache.ambari.server.controller.internal.OperationStatusMetaData;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.JsonGenerator;
@@ -112,6 +113,8 @@ public class JsonSerializer implements ResultSerializer {
 
     if (resultMetadata.getClass() == DeleteResultMetadata.class) {
       processResultMetadata((DeleteResultMetadata) resultMetadata);
+    } else if (resultMetadata.getClass() == OperationStatusMetaData.class) {
+      processResultMetadata((OperationStatusMetaData) resultMetadata);
     } else {
       throw new IllegalArgumentException("ResultDetails is not of type DeleteResultDetails, cannot parse");
     }
@@ -144,6 +147,30 @@ public class JsonSerializer implements ResultSerializer {
     m_generator.writeEndObject();
   }
 
+  private void processResultMetadata(OperationStatusMetaData metaData) throws IOException {
+    m_generator.writeStartObject();
+    m_generator.writeObjectFieldStart("operationResults");
+
+    for (OperationStatusMetaData.Result result : metaData.getResults()) {
+      m_generator.writeObjectFieldStart(result.getId());
+      m_generator.writeStringField("status", result.isSuccess() ? "success" : "error");
+
+      if (result.getMessage() != null) {
+        m_generator.writeStringField("message", result.getMessage());
+      }
+
+      if (result.getResponse() != null) {
+        m_generator.writeFieldName("response");
+        m_mapper.writeValue(m_generator, result.getResponse());
+      }
+
+      m_generator.writeEndObject();
+    }
+
+    m_generator.writeEndObject();
+    m_generator.writeEndObject();
+  }
+
   private void processNode(TreeNode<Resource> node) throws IOException {
     if (isObject(node)) {
       m_generator.writeStartObject();
@@ -158,10 +185,11 @@ public class JsonSerializer implements ResultSerializer {
     }
 
     if (isArray(node)) {
-      if (node.getName() != null)
+      if (node.getName() != null) {
         m_generator.writeArrayFieldStart(node.getName());
-      else
+      } else {
         m_generator.writeStartArray();
+      }
     }
 
     for (TreeNode<Resource> child : node.getChildren()) {
@@ -186,11 +214,11 @@ public class JsonSerializer implements ResultSerializer {
   // Determines whether or not the given node is an array
   private boolean isArray(TreeNode<Resource> node) {
     return (node.getObject() == null && node.getName() != null) ||
-            (node.getObject() == null && node.getName() == null &&
-             node.getChildren().size() > 1);
+        (node.getObject() == null && node.getName() == null &&
+            node.getChildren().size() > 1);
   }
 
-  private TreeNode<Map<String, Object>> getTreeProperties (Map<String, Map<String, Object>> propertiesMap) {
+  private TreeNode<Map<String, Object>> getTreeProperties(Map<String, Map<String, Object>> propertiesMap) {
     TreeNode<Map<String, Object>> treeProperties = new TreeNodeImpl<>(null, new LinkedHashMap<>(), null);
 
     for (Map.Entry<String, Map<String, Object>> entry : propertiesMap.entrySet()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index 4ec15ef..6e6b37e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -47,6 +47,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.controller.RootComponent;
 import org.apache.ambari.server.controller.RootService;
+import org.apache.ambari.server.controller.internal.AmbariServerConfigurationCategory;
 import org.apache.ambari.server.controller.internal.RootServiceComponentConfigurationResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.state.ServiceInfo;
@@ -78,7 +79,6 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
   private static final String GET_HOSTS_INFO_URI = "/api/v1/hosts"
       + "?fields=Hosts/*&Hosts/host_name.in(%s)";
-  static final String LDAP_CONFIGURATION_PROPERTY = "ldap-configuration";
 
   private static final String GET_SERVICES_INFO_URI = "/api/v1/stacks/%s/versions/%s/"
       + "?fields=Versions/stack_name,Versions/stack_version,Versions/parent_stack_version"
@@ -91,11 +91,11 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + "&services/StackServices/service_name.in(%s)";
 
   private static final String GET_AMBARI_LDAP_CONFIG_URI = String.format("/api/v1/services/%s/components/%s/configurations?%s=%s&fields=%s",
-    RootService.AMBARI.name(),
-    RootComponent.AMBARI_SERVER.name(),
-    RootServiceComponentConfigurationResourceProvider.CONFIGURATION_CATEGORY_PROPERTY_ID,
-    LDAP_CONFIGURATION_PROPERTY,
-    RootServiceComponentConfigurationResourceProvider.CONFIGURATION_PROPERTIES_PROPERTY_ID);
+      RootService.AMBARI.name(),
+      RootComponent.AMBARI_SERVER.name(),
+      RootServiceComponentConfigurationResourceProvider.CONFIGURATION_CATEGORY_PROPERTY_ID,
+      AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(),
+      RootServiceComponentConfigurationResourceProvider.CONFIGURATION_PROPERTIES_PROPERTY_ID);
 
   private static final String SERVICES_PROPERTY = "services";
   private static final String SERVICES_COMPONENTS_PROPERTY = "components";
@@ -230,7 +230,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
         throw new StackAdvisorException("Unexpected JSON document encountered: missing the Configuration/properties object");
       }
 
-      root.put(LDAP_CONFIGURATION_PROPERTY, ldapConfigurationProperties);
+      root.put(AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName(), ldapConfigurationProperties);
     } else if (numConfigs > 1) {
       throw new StackAdvisorException(String.format("Multiple (%s) LDAP configs are found in the DB.", numConfigs));
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
new file mode 100644
index 0000000..f4fc83f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationCategory.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ambari.server.controller.internal;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * AmbariServerConfigurationCategory is an enumeration of the different Ambari server specific
+ * configuration categories.
+ */
+public enum AmbariServerConfigurationCategory {
+  LDAP_CONFIGURATION("ldap-configuration");
+
+  private final String categoryName;
+
+  AmbariServerConfigurationCategory(String categoryName) {
+    this.categoryName = categoryName;
+  }
+
+  public String getCategoryName() {
+    return categoryName;
+  }
+
+  /**
+   * Safely returns an {@link AmbariServerConfigurationCategory} given the category's descriptive name
+   *
+   * @param categoryName a descriptive name
+   * @return an {@link AmbariServerConfigurationCategory}
+   */
+  public static AmbariServerConfigurationCategory translate(String categoryName) {
+    if (!StringUtils.isEmpty(categoryName)) {
+      categoryName = categoryName.trim();
+      for (AmbariServerConfigurationCategory category : values()) {
+        if (category.getCategoryName().equals(categoryName)) {
+          return category;
+        }
+      }
+    }
+
+    throw new IllegalArgumentException(String.format("Invalid Ambari server configuration category name: %s", categoryName));
+  }
+
+  /**
+   * Safely returns the {@link AmbariServerConfigurationCategory}'s descriptive name or <code>null</code>
+   * if no {@link AmbariServerConfigurationCategory} was supplied.
+   *
+   * @param category an {@link AmbariServerConfigurationCategory}
+   * @return the descriptive name of an {@link AmbariServerConfigurationCategory}
+   */
+  public static String translate(AmbariServerConfigurationCategory category) {
+    return (category == null) ? null : category.getCategoryName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
new file mode 100644
index 0000000..34285d6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerConfigurationHandler.java
@@ -0,0 +1,110 @@
+/*
+ * 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.ambari.server.controller.internal;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
+import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * AmbariServerConfigurationHandler handles Ambari server specific configuration properties.
+ */
+@StaticallyInject
+class AmbariServerConfigurationHandler extends RootServiceComponentConfigurationHandler {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerConfigurationHandler.class);
+
+  @Inject
+  private static AmbariConfigurationDAO ambariConfigurationDAO;
+
+  @Inject
+  private static AmbariEventPublisher publisher;
+
+
+  @Override
+  public Map<String, Map<String, String>> getConfigurations(String categoryName)
+      throws NoSuchResourceException {
+    Map<String, Map<String, String>> configurations = null;
+
+    List<AmbariConfigurationEntity> entities = (categoryName == null)
+        ? ambariConfigurationDAO.findAll()
+        : ambariConfigurationDAO.findByCategory(categoryName);
+
+    if (entities != null) {
+      configurations = new HashMap<>();
+
+      for (AmbariConfigurationEntity entity : entities) {
+        String category = entity.getCategoryName();
+        Map<String, String> properties = configurations.get(category);
+
+        if (properties == null) {
+          properties = new TreeMap<>();
+          configurations.put(category, properties);
+        }
+
+        properties.put(entity.getPropertyName(), entity.getPropertyValue());
+      }
+    }
+
+    return configurations;
+  }
+
+  @Override
+  public void removeConfiguration(String categoryName) throws NoSuchResourceException {
+    if (null == categoryName) {
+      LOGGER.debug("No resource id provided in the request");
+    } else {
+      LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName);
+      try {
+        if (ambariConfigurationDAO.removeByCategory(categoryName) > 0) {
+          publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
+        }
+      } catch (IllegalStateException e) {
+        throw new NoSuchResourceException(e.getMessage());
+      }
+    }
+  }
+
+  @Override
+  public void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified) {
+    if (ambariConfigurationDAO.reconcileCategory(categoryName, properties, removePropertiesIfNotSpecified)) {
+      // notify subscribers about the configuration changes
+      publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
+    }
+  }
+
+  @Override
+  public OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                          boolean mergeExistingProperties, String operation,
+                                          Map<String, Object> operationParameters) throws SystemException {
+    throw new SystemException(String.format("The requested operation is not supported for this category: %s", categoryName));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
new file mode 100644
index 0000000..6f16c49
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AmbariServerLDAPConfigurationHandler.java
@@ -0,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
+ *
+ *     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.ambari.server.controller.internal;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
+import org.apache.ambari.server.ldap.service.AmbariLdapException;
+import org.apache.ambari.server.ldap.service.LdapFacade;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+
+/**
+ * AmbariServerLDAPConfigurationHandler handles Ambari server LDAP-specific configuration properties.
+ */
+@StaticallyInject
+class AmbariServerLDAPConfigurationHandler extends AmbariServerConfigurationHandler {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AmbariServerLDAPConfigurationHandler.class);
+
+  @Inject
+  private static LdapFacade ldapFacade;
+
+  @Override
+  public OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                          boolean mergeExistingProperties, String operation, Map<String, Object> operationParameters) throws SystemException {
+
+    if (!AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName().equals(categoryName)) {
+      throw new SystemException(String.format("Unexpected category name for Ambari server LDAP properties: %s", categoryName));
+    }
+
+    OperationType operationType = OperationType.translate(operation);
+    if (operation == null) {
+      throw new SystemException("Unexpected operation for Ambari server LDAP properties");
+    }
+
+    Map<String, String> ldapConfigurationProperties = new HashMap<>();
+
+    // If we need to merge with the properties of an existing ldap-configuration property set, attempt
+    // to retrieve if. If one does not exist, that is ok.
+    if (mergeExistingProperties) {
+      try {
+        Map<String, Map<String, String>> _configurations = getConfigurations(categoryName);
+        if (_configurations != null) {
+          Map<String, String> _ldapProperties = _configurations.get(categoryName);
+
+          if (_ldapProperties != null) {
+            ldapConfigurationProperties.putAll(_ldapProperties);
+          }
+        }
+      } catch (NoSuchResourceException e) {
+        // Ignore this. There is no existing ldap-configuration category and that is ok.
+      }
+    }
+
+    if (properties != null) {
+      ldapConfigurationProperties.putAll(properties);
+    }
+
+    AmbariLdapConfiguration ambariLdapConfiguration = new AmbariLdapConfiguration(ldapConfigurationProperties);
+
+    boolean success = true;
+    String message = null;
+    Object resultData = null;
+
+    try {
+      switch (operationType) {
+        case TEST_CONNECTION:
+          LOGGER.debug("Testing connection to the LDAP server ...");
+          ldapFacade.checkConnection(ambariLdapConfiguration);
+          break;
+
+        case TEST_ATTRIBUTES:
+          LOGGER.debug("Testing LDAP attributes ....");
+          Set<String> groups = ldapFacade.checkLdapAttributes(operationParameters, ambariLdapConfiguration);
+          resultData = Collections.singletonMap("groups", groups);
+          break;
+
+        case DETECT_ATTRIBUTES:
+          LOGGER.info("Detecting LDAP attributes ...");
+          ambariLdapConfiguration = ldapFacade.detectAttributes(ambariLdapConfiguration);
+          resultData = Collections.singletonMap("attributes", ambariLdapConfiguration.toMap());
+          break;
+
+        default:
+          LOGGER.warn("No action provided ...");
+          throw new IllegalArgumentException("No request action provided");
+      }
+    } catch (AmbariLdapException e) {
+      success = false;
+      message = determineCause(e);
+      if (StringUtils.isEmpty(message)) {
+        message = "An unexpected error has occurred.";
+      }
+
+      LOGGER.warn(String.format("Failed to perform %s: %s", operationType.name(), message), e);
+    }
+
+    return new OperationResult(operationType.getOperation(), success, message, resultData);
+  }
+
+  private String determineCause(Throwable throwable) {
+    if (throwable == null) {
+      return null;
+    } else {
+      Throwable cause = throwable.getCause();
+      if ((cause == null) || (cause == throwable)) {
+        return throwable.getMessage();
+      } else {
+        String message = determineCause(cause);
+        return (message == null) ? throwable.getMessage() : message;
+      }
+    }
+  }
+
+  enum OperationType {
+    TEST_CONNECTION("test-connection"),
+    TEST_ATTRIBUTES("test-attributes"),
+    DETECT_ATTRIBUTES("detect-attributes");
+
+    private final String operation;
+
+    OperationType(String operation) {
+      this.operation = operation;
+    }
+
+    public String getOperation() {
+      return operation;
+    }
+
+    public static OperationType translate(String operation) {
+      if (!StringUtils.isEmpty(operation)) {
+        operation = operation.trim();
+        for (OperationType category : values()) {
+          if (category.getOperation().equals(operation)) {
+            return category;
+          }
+        }
+      }
+
+      throw new IllegalArgumentException(String.format("Invalid Ambari server configuration category name: %s", operation));
+    }
+
+    public static String translate(OperationType operation) {
+      return (operation == null) ? null : operation.getOperation();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
new file mode 100644
index 0000000..2467fc5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/OperationStatusMetaData.java
@@ -0,0 +1,90 @@
+/*
+ * 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.ambari.server.controller.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.ambari.server.api.services.ResultMetadata;
+import org.apache.ambari.server.controller.spi.RequestStatusMetaData;
+
+/**
+ * OperationStatusMetaData is data to return as the status of an operation invoked on a set of resources
+ * while processing a REST API request.
+ * <p>
+ * Zero or more results may be set as part of the data.
+ */
+public class OperationStatusMetaData implements RequestStatusMetaData, ResultMetadata {
+
+  private final Map<String, Result> results = new HashMap<>();
+
+  public void addResult(String id, boolean success, String message, Object response) {
+    results.put(id, new Result(id, success, message, response));
+  }
+
+  public Set<String> getResultIds() {
+    return results.keySet();
+  }
+
+  public Result getResult(String id) {
+    if (results.containsKey(id)) {
+      return results.get(id);
+    }
+
+    throw new NoSuchElementException();
+  }
+
+  public List<Result> getResults() {
+    return new ArrayList<>(results.values());
+  }
+
+  public class Result {
+    private final String id;
+    private final boolean success;
+    private final String message;
+    private final Object response;
+
+    Result(String id, boolean success, String message, Object response) {
+      this.id = id;
+      this.success = success;
+      this.message = message;
+      this.response = response;
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public boolean isSuccess() {
+      return success;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public Object getResponse() {
+      return response;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
new file mode 100644
index 0000000..3b58ce1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandler.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ambari.server.controller.internal;
+
+import java.util.Map;
+
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.SystemException;
+
+/**
+ * RootServiceComponentConfigurationHandler is an interface to be implemented to handle the different
+ * types of root-level configurations.
+ */
+abstract class RootServiceComponentConfigurationHandler {
+  /**
+   * Retrieve the request configurations.
+   *
+   * @param categoryName the category name (or <code>null</code> for all)
+   * @return a map of category names to properties (name/value pairs).
+   * @throws NoSuchResourceException if the requested data is not found
+   */
+  public abstract Map<String, Map<String, String>> getConfigurations(String categoryName) throws NoSuchResourceException;
+
+  /**
+   * Delete the requested configuration.
+   *
+   * @param categoryName the category name
+   * @throws NoSuchResourceException if the requested category does not exist
+   */
+  public abstract void removeConfiguration(String categoryName) throws NoSuchResourceException;
+
+  /**
+   * Set or update a configuration category with the specified properties.
+   * <p>
+   * If <code>removePropertiesIfNotSpecified</code> is <code>true</code>, the persisted category is to include only the specified properties.
+   * <p>
+   * If <code>removePropertiesIfNotSpecified</code> is <code>false</code>, the persisted category is to include the union of the existing and specified properties.
+   * <p>
+   * In any case, existing property values will be overwritten by the one specified in the property map.
+   *
+   * @param categoryName                   the category name
+   * @param properties                     a map of properties to set
+   * @param removePropertiesIfNotSpecified <code>true</code> to ensure the set of properties are only those that have be explicitly specified;
+   *                                       <code>false</code> to update the set of existing properties with the specified set of properties, adding missing properties but not removing any properties
+   */
+  public abstract void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified);
+
+  /**
+   * Preform some operation on the set of data for a category.
+   * <p>
+   * If <code>mergeExistingProperties</code> is <code>false</code>, the operation is to include the union of the existing and specified properties.
+   * <p>
+   * If <code>mergeExistingProperties</code> is <code>false</code>, the operation is to include only the specified properties.
+   *
+   * @param categoryName            the category name
+   * @param properties              a map of properties to set
+   * @param mergeExistingProperties <code>true</code> to use the the set of existing properties along with the specified set of properties;
+   *                                <code>false</code>  to use set of specified properties only
+   * @param operation               the operation to perform
+   * @param operationParameters     parameters to supply the name operation
+   * @return an {@link OperationResult}
+   * @throws SystemException if an error occurs while handling the request
+   */
+  public abstract OperationResult performOperation(String categoryName, Map<String, String> properties,
+                                                   boolean mergeExistingProperties, String operation,
+                                                   Map<String, Object> operationParameters) throws SystemException;
+
+  class OperationResult {
+    private final String id;
+    private final boolean success;
+    private final String message;
+    private final Object response;
+
+    OperationResult(String id, boolean success, String message, Object response) {
+      this.id = id;
+      this.success = success;
+      this.message = message;
+      this.response = response;
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public boolean isSuccess() {
+      return success;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public Object getResponse() {
+      return response;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
new file mode 100644
index 0000000..38b5373
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationHandlerFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.ambari.server.controller.internal;
+
+import org.apache.ambari.server.controller.RootComponent;
+import org.apache.ambari.server.controller.RootService;
+
+import com.google.inject.Singleton;
+
+/**
+ * RootServiceComponentConfigurationHandlerFactory produces RootServiceComponentConfigurationHandler
+ * implementations for the relevant service, component, and category.
+ */
+@Singleton
+public class RootServiceComponentConfigurationHandlerFactory {
+
+  /**
+   * Returns the internal configuration handler used to support various configuration storage facilities.
+   *
+   * @param serviceName   the service name
+   * @param componentName the component name
+   * @param categoryName  the category name
+   * @return a {@link RootServiceComponentConfigurationHandler}
+   */
+  public RootServiceComponentConfigurationHandler getInstance(String serviceName, String componentName, String categoryName) {
+    if (RootService.AMBARI.name().equals(serviceName)) {
+      if (RootComponent.AMBARI_SERVER.name().equals(componentName)) {
+        if (AmbariServerConfigurationCategory.LDAP_CONFIGURATION.getCategoryName().equals(categoryName)) {
+          return new AmbariServerLDAPConfigurationHandler();
+        } else {
+          return new AmbariServerConfigurationHandler();
+        }
+      }
+    }
+
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
index 7807865..b9e7d67 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentConfigurationResourceProvider.java
@@ -22,14 +22,11 @@ import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.controller.RootComponent;
-import org.apache.ambari.server.controller.RootService;
+import org.apache.ambari.server.api.services.RootServiceComponentConfigurationService;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -41,22 +38,14 @@ import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PredicateHelper;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.events.AmbariConfigurationChangedEvent;
-import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
-import org.apache.ambari.server.orm.dao.AmbariConfigurationDAO;
-import org.apache.ambari.server.orm.entities.AmbariConfigurationEntity;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
 
 public class RootServiceComponentConfigurationResourceProvider extends AbstractAuthorizedResourceProvider {
 
-  private static final Logger LOGGER = LoggerFactory.getLogger(RootServiceComponentConfigurationResourceProvider.class);
-
   static final String RESOURCE_KEY = "Configuration";
 
   public static final String CONFIGURATION_CATEGORY_PROPERTY_ID = PropertyHelper.getPropertyId(RESOURCE_KEY, "category");
@@ -89,10 +78,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   @Inject
-  private AmbariConfigurationDAO ambariConfigurationDAO;
-
-  @Inject
-  private AmbariEventPublisher publisher;
+  private RootServiceComponentConfigurationHandlerFactory rootServiceComponentConfigurationHandlerFactory;
 
   public RootServiceComponentConfigurationResourceProvider() {
     super(PROPERTIES, PK_PROPERTY_MAP);
@@ -113,9 +99,20 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   public RequestStatus createResourcesAuthorized(Request request)
       throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException {
 
-    createOrAddProperties(null, null, null, request.getProperties(), true);
+    OperationStatusMetaData operationStatusMetadata = null;
 
-    return getRequestStatus(null);
+    Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
+    if (requestInfoProperties.containsKey(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION)) {
+      String operationType = requestInfoProperties.get(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION);
+      Map<String, Object> operationParameters = getOperationParameters(requestInfoProperties);
+
+      operationStatusMetadata = performOperation(null, null, null, request.getProperties(),
+          false, operationType, operationParameters);
+    } else {
+      createOrAddProperties(null, null, null, request.getProperties(), true);
+    }
+
+    return getRequestStatus(null, null, operationStatusMetadata);
   }
 
   @Override
@@ -163,7 +160,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     });
   }
 
-
   @Override
   protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) throws SystemException,
       UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
@@ -172,7 +168,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     String componentName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
     String categoryName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    ConfigurationHandler handler = getConfigurationHandler(serviceName, componentName);
+    RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(serviceName, componentName, categoryName);
     if (handler != null) {
       handler.removeConfiguration(categoryName);
     } else {
@@ -190,9 +186,20 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     String componentName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
     String categoryName = (String) PredicateHelper.getProperties(predicate).get(CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    createOrAddProperties(serviceName, componentName, categoryName, request.getProperties(), false);
+    OperationStatusMetaData operationStatusMetadata = null;
 
-    return getRequestStatus(null);
+    Map<String, String> requestInfoProperties = request.getRequestInfoProperties();
+    if (requestInfoProperties.containsKey(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION)) {
+      String operationType = requestInfoProperties.get(RootServiceComponentConfigurationService.DIRECTIVE_OPERATION);
+      Map<String, Object> operationParameters = getOperationParameters(requestInfoProperties);
+
+      operationStatusMetadata = performOperation(serviceName, componentName, categoryName, request.getProperties(),
+          true, operationType, operationParameters);
+    } else {
+      createOrAddProperties(serviceName, componentName, categoryName, request.getProperties(), false);
+    }
+
+    return getRequestStatus(null, null, operationStatusMetadata);
   }
 
   private Resource toResource(String serviceName, String componentName, String categoryName, Map<String, String> properties, Set<String> requestedIds) {
@@ -211,7 +218,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
    * value and one or more property (<code>AmbariConfiguration/properties/property.name</code>) values.
    * If a category cannot be determined from the propery set, the default category value (passed in)
    * is used.  If a default category is set, it is assumed that it was parsed from the request predicate
-   * (if availabe).
+   * (if available).
    *
    * @param defaultServiceName             the default service name to use if needed
    * @param defaultComponentName           the default component name to use if needed
@@ -229,8 +236,7 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
       for (Map<String, Object> resourceProperties : requestProperties) {
         RequestDetails requestDetails = parseProperties(defaultServiceName, defaultComponentName, defaultCategoryName, resourceProperties);
 
-        ConfigurationHandler handler = getConfigurationHandler(requestDetails.serviceName, requestDetails.componentName);
-
+        RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(requestDetails.serviceName, requestDetails.componentName, requestDetails.categoryName);
         if (handler != null) {
           handler.updateCategory(requestDetails.categoryName, requestDetails.properties, removePropertiesIfNotSpecified);
         } else {
@@ -241,6 +247,49 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
+   * Performs the requested operation on the set of data for the specified configration data.
+   *
+   * @param defaultServiceName      the default service name to use if needed
+   * @param defaultComponentName    the default component name to use if needed
+   * @param defaultCategoryName     the default category to use if needed
+   * @param requestProperties       a collection of property maps parsed from the request
+   * @param mergeExistingProperties <code>true</code> to use the the set of existing properties along with the specified set of properties;
+   *                                <code>false</code>  to use set of specified properties only
+   * @param operationType           the operation to perform
+   * @param operationParameters     parameters to supply the name operation
+   * @return an {@link OperationStatusMetaData}
+   * @throws SystemException if an error occurs while performing the operation
+   */
+  private OperationStatusMetaData performOperation(String defaultServiceName, String defaultComponentName, String defaultCategoryName,
+                                                   Set<Map<String, Object>> requestProperties, boolean mergeExistingProperties,
+                                                   String operationType, Map<String, Object> operationParameters)
+      throws SystemException {
+
+    OperationStatusMetaData metaData = new OperationStatusMetaData();
+
+    // set of resource properties (each entry in the set belongs to a different resource)
+    if (requestProperties != null) {
+      for (Map<String, Object> resourceProperties : requestProperties) {
+        RequestDetails requestDetails = parseProperties(defaultServiceName, defaultComponentName, defaultCategoryName, resourceProperties);
+
+        RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(requestDetails.serviceName, requestDetails.componentName, requestDetails.categoryName);
+        if (handler != null) {
+          RootServiceComponentConfigurationHandler.OperationResult operationResult = handler.performOperation(requestDetails.categoryName, requestDetails.properties, mergeExistingProperties, operationType, operationParameters);
+          if (operationResult == null) {
+            throw new SystemException(String.format("An unexpected error has occurred while handling an operation for the %s component of the root service, %s", requestDetails.serviceName, requestDetails.componentName));
+          }
+
+          metaData.addResult(operationResult.getId(), operationResult.isSuccess(), operationResult.getMessage(), operationResult.getResponse());
+        } else {
+          throw new SystemException(String.format("Operations may not be performed on configurations for the %s component of the root service, %s", requestDetails.serviceName, requestDetails.componentName));
+        }
+      }
+    }
+
+    return metaData;
+  }
+
+  /**
    * Parse the property map from a request into a map of services to components to category names to maps of property names and values.
    *
    * @param defaultServiceName   the default service name to use if one is not found in the map of properties
@@ -300,7 +349,31 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
-   * Retrieves the requested configration resources
+   * Creates a map of the operation parameters from the data in the request info map.
+   * <p>
+   * Operation parmaters are set under the "parameters" category.
+   *
+   * @param requestInfoProperties a map of request info properties
+   * @return a map of operation request parameters
+   */
+  private Map<String, Object> getOperationParameters(Map<String, String> requestInfoProperties) {
+    Map<String, Object> operationParameters = new HashMap<>();
+
+    for (Map.Entry<String, String> entry : requestInfoProperties.entrySet()) {
+      String propertyCategory = PropertyHelper.getPropertyCategory(entry.getKey());
+      if ((propertyCategory != null) && propertyCategory.equals("parameters")) {
+        String name = PropertyHelper.getPropertyName(entry.getKey());
+        Object value = entry.getValue();
+        operationParameters.put(name, (value == null) ? null : value.toString());
+      }
+    }
+
+    return operationParameters;
+  }
+
+
+  /**
+   * Retrieves the requested configuration resources
    *
    * @param requestedIds the requested properties ids
    * @param propertyMap  the request properties
@@ -312,11 +385,11 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
 
     String serviceName = getStringProperty(propertyMap, CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
     String componentName = getStringProperty(propertyMap, CONFIGURATION_COMPONENT_NAME_PROPERTY_ID);
+    String categoryName = getStringProperty(propertyMap, CONFIGURATION_CATEGORY_PROPERTY_ID);
 
-    ConfigurationHandler handler = getConfigurationHandler(serviceName, componentName);
+    RootServiceComponentConfigurationHandler handler = rootServiceComponentConfigurationHandlerFactory.getInstance(serviceName, componentName, categoryName);
 
     if (handler != null) {
-      String categoryName = getStringProperty(propertyMap, CONFIGURATION_CATEGORY_PROPERTY_ID);
       Map<String, Map<String, String>> configurations = handler.getConfigurations(categoryName);
 
       if (configurations != null) {
@@ -329,24 +402,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
     return resources;
   }
 
-  /**
-   * Returns the internal configuration handler used to support various configuration storage facilites.
-   *
-   * @param serviceName   the service name
-   * @param componentName the component name
-   * @return
-   */
-  private ConfigurationHandler getConfigurationHandler(String serviceName, String componentName) {
-    if (RootService.AMBARI.name().equals(serviceName)) {
-      if (RootComponent.AMBARI_SERVER.name().equals(componentName)) {
-        return new AmbariServerConfigurationHandler();
-      }
-    }
-
-    return null;
-  }
-
-
   private String getStringProperty(Map<String, Object> propertyMap, String propertyId) {
     String value = null;
 
@@ -361,102 +416,6 @@ public class RootServiceComponentConfigurationResourceProvider extends AbstractA
   }
 
   /**
-   * ConfigurationHandler is an interface to be implemented to support the relevant types of storage
-   * used to persist root-level component configurations.
-   */
-  private abstract class ConfigurationHandler {
-    /**
-     * Retrieve the request configurations.
-     *
-     * @param categoryName the category name (or <code>null</code> for all)
-     * @return a map of category names to properties (name/value pairs).
-     * @throws NoSuchResourceException if the requested data is not found
-     */
-    public abstract Map<String, Map<String, String>> getConfigurations(String categoryName) throws NoSuchResourceException;
-
-    /**
-     * Delete the requested configuration.
-     *
-     * @param categoryName the category name
-     * @throws NoSuchResourceException if the requested category does not exist
-     */
-    public abstract void removeConfiguration(String categoryName) throws NoSuchResourceException;
-
-    /**
-     * Set or update a configuration category with the specified properties.
-     * <p>
-     * If <code>removePropertiesIfNotSpecified</code> is <code>true</code>, the persisted category is to include only the specified properties.
-     * <p>
-     * If <code>removePropertiesIfNotSpecified</code> is <code>false</code>, the persisted category is to include the union of the existing and specified properties.
-     * <p>
-     * In any case, existing property values will be overwritten by the one specified in the property map.
-     *
-     * @param categoryName                   the category name
-     * @param properties                     a map of properties to set
-     * @param removePropertiesIfNotSpecified <code>true</code> to ensure the set of properties are only those that have be explicitly specified;
-     *                                       <code>false</code> to update the set of exising properties with the specified set of properties, adding missing properties but not removing any properties
-     */
-    public abstract void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified);
-  }
-
-  /**
-   * AmbariServerConfigurationHandler handle Ambari server specific configuration properties.
-   */
-  private class AmbariServerConfigurationHandler extends ConfigurationHandler {
-    @Override
-    public Map<String, Map<String, String>> getConfigurations(String categoryName)
-        throws NoSuchResourceException {
-      Map<String, Map<String, String>> configurations = null;
-
-      List<AmbariConfigurationEntity> entities = (categoryName == null)
-          ? ambariConfigurationDAO.findAll()
-          : ambariConfigurationDAO.findByCategory(categoryName);
-
-      if (entities != null) {
-        configurations = new HashMap<>();
-
-        for (AmbariConfigurationEntity entity : entities) {
-          String category = entity.getCategoryName();
-          Map<String, String> properties = configurations.get(category);
-
-          if (properties == null) {
-            properties = new TreeMap<>();
-            configurations.put(category, properties);
-          }
-
-          properties.put(entity.getPropertyName(), entity.getPropertyValue());
-        }
-      }
-
-      return configurations;
-    }
-
-    @Override
-    public void removeConfiguration(String categoryName) throws NoSuchResourceException {
-      if (null == categoryName) {
-        LOGGER.debug("No resource id provided in the request");
-      } else {
-        LOGGER.debug("Deleting Ambari configuration with id: {}", categoryName);
-        try {
-          if (ambariConfigurationDAO.removeByCategory(categoryName) > 0) {
-            publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-          }
-        } catch (IllegalStateException e) {
-          throw new NoSuchResourceException(e.getMessage());
-        }
-      }
-    }
-
-    @Override
-    public void updateCategory(String categoryName, Map<String, String> properties, boolean removePropertiesIfNotSpecified) {
-      if (ambariConfigurationDAO.reconcileCategory(categoryName, properties, removePropertiesIfNotSpecified)) {
-        // notify subscribers about the configuration changes
-        publisher.publish(new AmbariConfigurationChangedEvent(categoryName));
-      }
-    }
-  }
-
-  /**
    * RequestDetails is a container for details parsed from the request.
    */
   private class RequestDetails {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
index 089da1d..64e94c4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/LdapModule.java
@@ -16,7 +16,6 @@
 package org.apache.ambari.server.ldap;
 
 import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration;
-import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory;
 import org.apache.ambari.server.ldap.service.AmbariLdapConfigurationProvider;
 import org.apache.ambari.server.ldap.service.AmbariLdapFacade;
 import org.apache.ambari.server.ldap.service.AttributeDetector;
@@ -36,7 +35,6 @@ import org.apache.ambari.server.ldap.service.ads.detectors.UserNameAttrDetector;
 import org.apache.ambari.server.ldap.service.ads.detectors.UserObjectClassDetector;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 
@@ -60,8 +58,6 @@ public class LdapModule extends AbstractModule {
 
     bind(AttributeDetectorFactory.class);
 
-    install(new FactoryModuleBuilder().build(AmbariLdapConfigurationFactory.class));
-
     // binding the set of user attributes detector
     Multibinder<AttributeDetector> userAttributeDetectorBinder = Multibinder.newSetBinder(binder(), AttributeDetector.class,
       Names.named(USER_ATTRIBUTES_DETECTORS));

http://git-wip-us.apache.org/repos/asf/ambari/blob/4240f849/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
deleted file mode 100644
index da655ad..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/domain/AmbariLdapConfigKeys.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.ldap.domain;
-
-/**
- * Constants representing supported LDAP related property names
- * // todo extend this with validation information, description, defaults maybe
- */
-public enum AmbariLdapConfigKeys {
-
-  LDAP_ENABLED("ambari.ldap.authentication.enabled"),
-  SERVER_HOST("ambari.ldap.connectivity.server.host"),
-  SERVER_PORT("ambari.ldap.connectivity.server.port"),
-  USE_SSL("ambari.ldap.connectivity.use_ssl"),
-
-  TRUST_STORE("ambari.ldap.connectivity.trust_store"),
-  TRUST_STORE_TYPE("ambari.ldap.connectivity.trust_store.type"),
-  TRUST_STORE_PATH("ambari.ldap.connectivity.trust_store.path"),
-  TRUST_STORE_PASSWORD("ambari.ldap.connectivity.trust_store.password"),
-  ANONYMOUS_BIND("ambari.ldap.connectivity.anonymous_bind"),
-
-  BIND_DN("ambari.ldap.connectivity.bind_dn"),
-  BIND_PASSWORD("ambari.ldap.connectivity.bind_password"),
-
-  ATTR_DETECTION("ambari.ldap.attributes.detection"), // manual | auto
-
-  DN_ATTRIBUTE("ambari.ldap.attributes.dn_attr"),
-
-  USER_OBJECT_CLASS("ambari.ldap.attributes.user.object_class"),
-  USER_NAME_ATTRIBUTE("ambari.ldap.attributes.user.name_attr"),
-  USER_GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.user.group_member_attr"),
-  USER_SEARCH_BASE("ambari.ldap.attributes.user.search_base"),
-
-  GROUP_OBJECT_CLASS("ambari.ldap.attributes.group.object_class"),
-  GROUP_NAME_ATTRIBUTE("ambari.ldap.attributes.group.name_attr"),
-  GROUP_MEMBER_ATTRIBUTE("ambari.ldap.attributes.group.member_attr"),
-  GROUP_SEARCH_BASE("ambari.ldap.attributes.group.search_base"),
-
-  USER_SEARCH_FILTER("ambari.ldap.advanced.user_search_filter"),
-  USER_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.user_member_replace_pattern"),
-  USER_MEMBER_FILTER("ambari.ldap.advanced.user_member_filter"),
-
-  GROUP_SEARCH_FILTER("ambari.ldap.advanced.group_search_filter"),
-  GROUP_MEMBER_REPLACE_PATTERN("ambari.ldap.advanced.group_member_replace_pattern"),
-  GROUP_MEMBER_FILTER("ambari.ldap.advanced.group_member_filter"),
-
-  FORCE_LOWERCASE_USERNAMES("ambari.ldap.advanced.force_lowercase_usernames"),
-  REFERRAL_HANDLING("ambari.ldap.advanced.referrals"), // folow
-  PAGINATION_ENABLED("ambari.ldap.advanced.pagination_enabled"); // true | false
-
-  private String propertyName;
-
-  AmbariLdapConfigKeys(String propName) {
-    this.propertyName = propName;
-  }
-
-  public String key() {
-    return this.propertyName;
-  }
-
-  public static AmbariLdapConfigKeys fromKeyStr(String keyStr) {
-    for (AmbariLdapConfigKeys key : values()) {
-      if (key.key().equals(keyStr)) {
-        return key;
-      }
-    }
-
-    throw new IllegalStateException("invalid konfiguration key found!");
-
-  }
-}


Mime
View raw message