You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ma...@apache.org on 2012/10/09 19:02:02 UTC

svn commit: r1396109 [2/7] - in /incubator/ambari/branches/AMBARI-666: ./ ambari-api/ ambari-project/ ambari-server/ ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ ambari-server/src/main/java/org/apache/ambari/server/api/query/ amba...

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,148 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ClusterResourceDefinition;
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+
+
+/**
+ * Service responsible for cluster resource requests.
+ */
+@Path("/clusters/")
+public class ClusterService extends BaseService {
+
+  /**
+   * Handles: GET /clusters/{clusterID}
+   * Get a specific cluster.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param clusterName cluster id
+   * @return cluster instance representation
+   */
+  @GET
+  @Path("{clusterName}")
+  @Produces("text/plain")
+  public Response getCluster(@Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("clusterName") String clusterName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(clusterName));
+  }
+
+  /**
+   * Handles: GET  /clusters
+   * Get all clusters.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return cluster collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getClusters(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(null));
+  }
+
+  /**
+   * Handles: PUT /clusters/{clusterID}
+   * Create a specific cluster.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param clusterName cluster id
+   * @return information regarding the created cluster
+   */
+  @PUT
+  @Produces("text/plain")
+  public Response createCluster(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("clusterName") String clusterName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResourceDefinition(clusterName));
+  }
+
+  /**
+   * Handles: POST /clusters/{clusterID}
+   * Update a specific cluster.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param clusterName cluster id
+   * @return information regarding the updated cluster
+   */
+  @POST
+  @Produces("text/plain")
+  public Response updateCluster(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("clusterName") String clusterName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST, createResourceDefinition(clusterName));
+  }
+
+  /**
+   * Handles: DELETE /clusters/{clusterID}
+   * Delete a specific cluster.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param clusterName cluster id
+   * @return information regarding the deleted cluster
+   */
+  @DELETE
+  @Produces("text/plain")
+  public Response deleteCluster(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("clusterName") String clusterName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResourceDefinition(clusterName));
+  }
+
+  /**
+   * Get the hosts sub-resource
+   *
+   * @param clusterName cluster id
+   * @return the hosts service
+   */
+  @Path("{clusterName}/hosts")
+  public HostService getHostHandler(@PathParam("clusterName") String clusterName) {
+    return new HostService(clusterName);
+  }
+
+  /**
+   * Get the services sub-resource
+   *
+   * @param clusterName cluster id
+   * @return the services service
+   */
+  @Path("{clusterName}/services")
+  public ServiceService getServiceHandler(@PathParam("clusterName") String clusterName) {
+    return new ServiceService(clusterName);
+  }
+
+  /**
+   * Create a cluster resource definition.
+   *
+   * @param clusterName cluster name
+   * @return a cluster resource definition
+   */
+  ResourceDefinition createResourceDefinition(String clusterName) {
+    return new ClusterResourceDefinition(clusterName);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ComponentService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ComponentService.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ComponentService.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ComponentService.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,155 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ComponentResourceDefinition;
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+
+/**
+ * Service responsible for components resource requests.
+ */
+public class ComponentService extends BaseService {
+  /**
+   * Parent cluster id.
+   */
+  private String m_clusterName;
+
+  /**
+   * Parent service id.
+   */
+  private String m_serviceName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster id
+   * @param serviceName service id
+   */
+  public ComponentService(String clusterName, String serviceName) {
+    m_clusterName = clusterName;
+    m_serviceName = serviceName;
+  }
+
+  /**
+   * Handles GET: /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Get a specific component.
+   *
+   * @param headers       http headers
+   * @param ui            uri info
+   * @param componentName component id
+   * @return a component resource representation
+   */
+  @GET
+  @Path("{componentName}")
+  @Produces("text/plain")
+  public Response getComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                               @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createResourceDefinition(componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles GET: /clusters/{clusterID}/services/{serviceID}/components
+   * Get all components for a service.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return component collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getComponents(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createResourceDefinition(null, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles: PUT /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Create a specific component.
+   *
+   * @param body          http body
+   * @param headers       http headers
+   * @param ui            uri info
+   * @param componentName component id
+   *
+   * @return information regarding the created component
+   */
+  @PUT
+  @Produces("text/plain")
+  public Response createComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles: POST /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Update a specific component.
+   *
+   * @param body                http body
+   * @param headers       http headers
+   * @param ui            uri info
+   * @param componentName component id
+   *
+   * @return information regarding the updated component
+   */
+  @POST
+  @Produces("text/plain")
+  public Response updateComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST, createResourceDefinition(
+        componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Handles: DELETE /clusters/{clusterID}/services/{serviceID}/components/{componentID}
+   * Delete a specific component.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param componentName cluster id
+   * @return information regarding the deleted cluster
+   */
+  @DELETE
+  @Produces("text/plain")
+  public Response deleteComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createResourceDefinition(
+        componentName, m_clusterName, m_serviceName));
+  }
+
+  /**
+   * Create a component resource definition.
+   *
+   * @param clusterName   cluster name
+   * @param serviceName   service name
+   * @param componentName component name
+   * @return a component resource definition
+   */
+  ResourceDefinition createResourceDefinition(String clusterName, String serviceName, String componentName) {
+    return new ComponentResourceDefinition(clusterName, serviceName, componentName);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/CreatePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/CreatePersistenceManager.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/CreatePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/CreatePersistenceManager.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,51 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+
+import java.util.Map;
+
+/**
+ * Responsible for persisting the creation of a resource in the back end.
+ */
+public class CreatePersistenceManager extends BasePersistenceManager {
+  @Override
+  public void persist(ResourceDefinition resource) {
+    ClusterController controller = getClusterController();
+    Map<Resource.Type, String> mapResourceIds = resource.getResourceIds();
+    Resource.Type type = resource.getType();
+    Schema schema = controller.getSchema(type);
+
+    for (Map.Entry<Resource.Type, String> entry : mapResourceIds.entrySet()) {
+      resource.setProperty(schema.getKeyPropertyId(entry.getKey()), entry.getValue());
+    }
+    try {
+      controller.createResources(type, createControllerRequest(resource.getProperties()));
+    } catch (AmbariException e) {
+      //todo: handle exception
+      throw new RuntimeException("Create of resource failed: " + e, e);
+
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeletePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeletePersistenceManager.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeletePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/DeletePersistenceManager.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,38 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.AmbariException;
+
+/**
+ * Responsible for persisting the deletion of a resource in the back end.
+ */
+public class DeletePersistenceManager extends BasePersistenceManager {
+  @Override
+  public void persist(ResourceDefinition resource) {
+    try {
+      getClusterController().deleteResources(resource.getType(),
+          resource.getQuery().getPredicate());
+    } catch (AmbariException e) {
+      //todo: handle exception
+      throw new RuntimeException("Delete of resource failed: " + e, e);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostComponentService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostComponentService.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostComponentService.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostComponentService.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,159 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.HostComponentResourceDefinition;
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+
+/**
+ * Service responsible for host_components resource requests.
+ */
+public class HostComponentService extends BaseService {
+  /**
+   * Parent cluster id.
+   */
+  private String m_clusterName;
+
+  /**
+   * Parent host id.
+   */
+  private String m_hostName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster id
+   * @param hostName    host id
+   */
+  public HostComponentService(String clusterName, String hostName) {
+    m_clusterName = clusterName;
+    m_hostName = hostName;
+  }
+
+  /**
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Get a specific host_component.
+   *
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   * @return host_component resource representation
+   */
+  @GET
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response getHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}/host_components/
+   * Get all host components for a host.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return host_component collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getHostComponents(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createResourceDefinition(null, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles PUT /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Create a specific host_component.
+   *
+   * @param body              http body
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @PUT
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response createHostComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles POST /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Updates a specific host_component.
+   *
+   * @param body              http body
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @POST
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response updateHostComponent(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                      @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Handles DELETE /clusters/{clusterID}/hosts/{hostID}/host_components/{hostComponentID}
+   * Delete a specific host_component.
+   *
+   * @param headers           http headers
+   * @param ui                uri info
+   * @param hostComponentName host_component id
+   *
+   * @return host_component resource representation
+   */
+  @DELETE
+  @Path("{hostComponentName}")
+  @Produces("text/plain")
+  public Response deleteHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("hostComponentName") String hostComponentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE,
+        createResourceDefinition(hostComponentName, m_clusterName, m_hostName));
+  }
+
+  /**
+   * Create a host_component resource definition.
+   *
+   * @param hostComponentName host_component name
+   * @param clusterName       cluster name
+   * @param hostName          host name
+   * @return a host resource definition
+   */
+  ResourceDefinition createResourceDefinition(String hostComponentName, String clusterName, String hostName) {
+    return new HostComponentResourceDefinition(hostComponentName, clusterName, hostName);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,163 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.HostResourceDefinition;
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+
+/**
+ * Service responsible for hosts resource requests.
+ */
+public class HostService extends BaseService {
+
+  /**
+   * Parent cluster id.
+   */
+  private String m_clusterName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster id
+   */
+  public HostService(String clusterName) {
+    m_clusterName = clusterName;
+  }
+
+  /**
+   * Handles GET /clusters/{clusterID}/hosts/{hostID}
+   * Get a specific host.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   * @return host resource representation
+   */
+  @GET
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response getHost(@Context HttpHeaders headers, @Context UriInfo ui,
+                          @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Handles GET /clusters/{clusterID}/hosts or /clusters/hosts
+   * Get all hosts for a cluster.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return host collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getHosts(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResourceDefinition(null, m_clusterName));
+  }
+
+  /**
+   * Handles PUT /clusters/{clusterID}/hosts/{hostID}
+   * Create a specific host.
+   *
+   * @param body     http body
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+
+  @PUT
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response createHost(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                          @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Handles POST /clusters/{clusterID}/hosts/{hostID}
+   * Updates a specific host.
+   *
+   * @param body     http body
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+  @POST
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response updateHost(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                          @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Handles DELETE /clusters/{clusterID}/hosts/{hostID}
+   * Deletes a specific host.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param hostName host id
+   *
+   * @return host resource representation
+   */
+  @DELETE
+  @Path("{hostName}")
+  @Produces("text/plain")
+  public Response deleteHost(@Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE,
+        createResourceDefinition(hostName, m_clusterName));
+  }
+
+  /**
+   * Get the host_components sub-resource.
+   *
+   * @param hostName host id
+   * @return the host_components service
+   */
+  @Path("{hostName}/host_components")
+  public HostComponentService getHostComponentHandler(@PathParam("hostName") String hostName) {
+    return new HostComponentService(m_clusterName, hostName);
+  }
+
+  /**
+   * Create a host resource definition.
+   *
+   * @param hostName    host name
+   * @param clusterName cluster name
+   * @return a host resource definition
+   */
+  ResourceDefinition createResourceDefinition(String hostName, String clusterName) {
+    return new HostResourceDefinition(hostName, clusterName);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/PersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/PersistenceManager.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/PersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/PersistenceManager.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,35 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+/**
+ * Persistence manager which is responsible for persisting a resource state to the back end.
+ * This includes create, update and delete operations.
+ */
+public interface PersistenceManager {
+  /**
+   * Persist a resource to the back end.
+   *
+   * @param resource  the resource to persist
+   *
+   */
+  public void persist(ResourceDefinition resource);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,131 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides information on the current request.
+ */
+public interface Request {
+
+  /**
+   * Enum of request types.
+   */
+  public enum Type {
+    GET,
+    PUT,
+    POST,
+    DELETE
+  }
+
+  /**
+   * Obtain the resource definition which corresponds to the resource being operated on by the request.
+   * The resource definition provides information about the resource type;
+   *
+   * @return the associated {@link ResourceDefinition}
+   */
+  public ResourceDefinition getResourceDefinition();
+
+  /**
+   * Obtain the URI of this request.
+   *
+   * @return the request uri
+   */
+  public URI getURI();
+
+  /**
+   * Obtain the http request type.  Type is one of {@link Type}.
+   *
+   * @return the http request type
+   */
+  public Type getRequestType();
+
+  /**
+   * Obtain the api version of the request.  The api version is specified in the request URI.
+   *
+   * @return the api version of the request
+   */
+  public int getAPIVersion();
+
+  /**
+   * Obtain the query predicates that were provided in the URL query string.
+   *
+   * @return a map of request predicates
+   */
+  public Map<String, String> getQueryPredicates();
+
+  /**
+   * Obtain the set of partial response fields which were provided in the query string of the request uri.
+   *
+   * @return a set of the provided partial response fields
+   */
+  public Set<String> getPartialResponseFields();
+
+  /**
+   * Obtain the result serializer for the request. The default serializer is of type JSON.
+   *
+   * @return the result serializer for the request
+   */
+  public ResultSerializer getResultSerializer();
+
+  /**
+   * Obtain the processor which processes the result returned from the request handler.
+   * The post processor adds additional information such as href fields to the result.
+   *
+   * @return the result processor associated with the request
+   */
+  public ResultPostProcessor getResultPostProcessor();
+
+  /**
+   * Obtain the http headers associated with the request.
+   *
+   * @return the http headers
+   */
+  public Map<String, List<String>> getHttpHeaders();
+
+  /**
+   * Obtain the http body associated with the request.
+   *
+   * @return the http body
+   */
+  public String getHttpBody();
+
+  /**
+   * Obtain the properties which have been parsed from the http body.
+   *
+   * @return a map containing the properties contained in the http body
+   */
+  public Map<PropertyId, String> getHttpBodyProperties();
+
+    //TODO: refactor persistence mechanism
+  /**
+   * Obtain the appropriate persistence manager.
+   *
+   * @return the appropriate persistence manager
+   */
+  public PersistenceManager getPersistenceManager();
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestFactory.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,44 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Factory for {@link Request} instances.
+ */
+public class RequestFactory {
+  /**
+   * Create a request instance.
+   *
+   * @param headers            http headers
+   * @param uriInfo            uri information
+   * @param requestType        http request type
+   * @param resourceDefinition associated resource definition
+   * @return a new Request instance
+   */
+  public Request createRequest(HttpHeaders headers, String body, UriInfo uriInfo, Request.Type requestType,
+                               ResourceDefinition resourceDefinition) {
+
+    return new RequestImpl(headers, body, uriInfo, requestType, resourceDefinition);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestImpl.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestImpl.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/RequestImpl.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,163 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.*;
+import org.apache.ambari.server.api.services.parsers.JsonPropertyParser;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.JsonSerializer;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+import java.util.*;
+
+/**
+ * Request implementation.
+ */
+public class RequestImpl implements Request {
+
+  /**
+   * URI information
+   */
+  private UriInfo m_uriInfo;
+
+  /**
+   * Http headers
+   */
+  private HttpHeaders m_headers;
+
+  /**
+   * Http Body
+   */
+  private String m_body;
+
+  /**
+   * Http request type
+   */
+  private Type m_Type;
+
+  /**
+   * Associated resource definition
+   */
+  private ResourceDefinition m_resourceDefinition;
+
+
+  /**
+   * Constructor.
+   *
+   * @param headers            http headers
+   * @param body               http body
+   * @param uriInfo            uri information
+   * @param requestType        http request type
+   * @param resourceDefinition associated resource definition
+   */
+  public RequestImpl(HttpHeaders headers, String body, UriInfo uriInfo, Type requestType,
+                     ResourceDefinition resourceDefinition) {
+
+    m_headers            = headers;
+    m_body               = body;
+    m_uriInfo            = uriInfo;
+    m_Type               = requestType;
+    m_resourceDefinition = resourceDefinition;
+  }
+
+  @Override
+  public ResourceDefinition getResourceDefinition() {
+    return m_resourceDefinition;
+  }
+
+  @Override
+  public URI getURI() {
+    return m_uriInfo.getRequestUri();
+  }
+
+  @Override
+  public Type getRequestType() {
+    return m_Type;
+  }
+
+  @Override
+  public int getAPIVersion() {
+    return 0;
+  }
+
+  @Override
+  public Map<String, String> getQueryPredicates() {
+    return null;
+  }
+
+  @Override
+  public Set<String> getPartialResponseFields() {
+    String partialResponseFields = m_uriInfo.getQueryParameters().getFirst("fields");
+    if (partialResponseFields == null) {
+      return Collections.emptySet();
+    } else {
+      return new HashSet<String>(Arrays.asList(partialResponseFields.split(",")));
+    }
+  }
+
+  @Override
+  public Map<String, List<String>> getHttpHeaders() {
+    return m_headers.getRequestHeaders();
+  }
+
+  @Override
+  public String getHttpBody() {
+    return m_body;
+  }
+
+  @Override
+  public Map<PropertyId, String> getHttpBodyProperties() {
+    return m_body == null ? Collections.<PropertyId, String>emptyMap() :
+        getHttpBodyParser().parse(getHttpBody());
+  }
+
+  @Override
+  public ResultSerializer getResultSerializer() {
+    return new JsonSerializer();
+  }
+
+  @Override
+  public ResultPostProcessor getResultPostProcessor() {
+    return new ResultPostProcessorImpl(this);
+  }
+
+  @Override
+  public PersistenceManager getPersistenceManager() {
+    switch (getRequestType()) {
+      case PUT:
+        return new CreatePersistenceManager();
+      case POST:
+        return new UpdatePersistenceManager();
+      case DELETE:
+        return new DeletePersistenceManager();
+      case GET:
+        throw new IllegalStateException("Tried to get persistence manager for get operation");
+      default:
+        throw new IllegalStateException("Tried to get persistence manager for unknown operation type");
+    }
+  }
+
+  private  RequestBodyParser getHttpBodyParser() {
+    return new JsonPropertyParser();
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResponseFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResponseFactory.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResponseFactory.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResponseFactory.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,37 @@
+/**
+ * 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.api.services;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * Factory for creating jax-rs responses from results.
+ */
+public class ResponseFactory {
+  /**
+   * Create a response from a provided result.
+   *
+   * @param result  the result to wrap
+   *
+   * @return a new jax-rs Response instance for the provided result
+   */
+  public Response createResponse(Object result) {
+    return Response.ok(result).build();
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Result.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Result.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Result.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/Result.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,35 @@
+/**
+ * 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.api.services;
+
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.api.util.TreeNode;
+
+/**
+ * Represents a result from a request handler invocation.
+ */
+public interface Result {
+  /**
+   * the results of the request invocation as a Tree structure.
+   *
+   * @return the results of the request a a Tree structure
+   */
+  public TreeNode<Resource> getResultTree();
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultImpl.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultImpl.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultImpl.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,43 @@
+/**
+ * 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.api.services;
+
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.api.util.TreeNode;
+import org.apache.ambari.server.api.util.TreeNodeImpl;
+
+
+/**
+ * Result implementation.
+ */
+public class ResultImpl implements Result {
+
+  /**
+   * Tree structure which holds the results
+   */
+  private TreeNode<Resource> m_tree = new TreeNodeImpl<Resource>(null, null, null);
+
+
+  @Override
+  public TreeNode<Resource> getResultTree() {
+    return m_tree;
+  }
+}
+

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessor.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessor.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessor.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessor.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,33 @@
+/**
+ * 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.api.services;
+
+/**
+ * Processor which processes result objects prior to them being returned to the service.
+ * Processing can include adding additional data such as hrefs, or modifying/deleting existing data.
+ */
+public interface ResultPostProcessor {
+  /**
+   * Process the given result.
+   * The passed in process is directly modified.
+   *
+   * @param result the result to process.
+   */
+  public void process(Result result);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,115 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.api.util.TreeNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Processes returned results to add href's and other content.
+ */
+public class ResultPostProcessorImpl implements ResultPostProcessor {
+  /**
+   * the associated request
+   */
+  private Request m_request;
+
+  /**
+   * Map of resource post processors keyed by resource type.
+   * These are used to act on specific resource types contained in the result.
+   */
+  Map<Resource.Type, List<ResourceDefinition.PostProcessor>> m_mapPostProcessors =
+      new HashMap<Resource.Type, List<ResourceDefinition.PostProcessor>>();
+
+
+  /**
+   * Constructor.
+   *
+   * @param request the associated request
+   */
+  public ResultPostProcessorImpl(Request request) {
+    m_request = request;
+
+    registerResourceProcessors(m_request.getResourceDefinition());
+  }
+
+  @Override
+  public void process(Result result) {
+    processNode(result.getResultTree(), m_request.getURI().toString());
+  }
+
+  /**
+   * Process a node of the result tree.  Recursively calls child nodes.
+   *
+   * @param node the node to process
+   * @param href the current href
+   */
+  private void processNode(TreeNode<Resource> node, String href) {
+    Resource r = node.getObject();
+    if (r != null) {
+      List<ResourceDefinition.PostProcessor> listProcessors = m_mapPostProcessors.get(r.getType());
+      for (ResourceDefinition.PostProcessor processor : listProcessors) {
+        processor.process(m_request, node, href);
+      }
+      href = node.getProperty("href");
+      int i = href.indexOf('?');
+      if (i != -1) {
+        href = href.substring(0, i);
+      }
+    } else {
+      String isItemsCollection = node.getProperty("isCollection");
+      if (node.getName() == null && "true".equals(isItemsCollection)) {
+        node.setName("items");
+        node.setProperty("href", href);
+      }
+    }
+    for (TreeNode<Resource> child : node.getChildren()) {
+      processNode(child, href);
+    }
+  }
+
+  /**
+   * Registers the resource processors.
+   * Recursively registers child resource processors.
+   *
+   * @param resource the root resource
+   */
+  private void registerResourceProcessors(ResourceDefinition resource) {
+    List<ResourceDefinition.PostProcessor> listProcessors = m_mapPostProcessors.get(resource.getType());
+    if (listProcessors == null) {
+      listProcessors = new ArrayList<ResourceDefinition.PostProcessor>();
+      m_mapPostProcessors.put(resource.getType(), listProcessors);
+    }
+    listProcessors.addAll(resource.getPostProcessors());
+
+    for (ResourceDefinition child : resource.getSubResources().values()) {
+      // avoid cycle
+      if (!m_mapPostProcessors.containsKey(child.getType())) {
+        registerResourceProcessors(child);
+      }
+    }
+  }
+
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,154 @@
+/**
+ * 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.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.api.resources.ServiceResourceDefinition;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.*;
+
+/**
+ * Service responsible for services resource requests.
+ */
+public class ServiceService extends BaseService {
+  /**
+   * Parent cluster name.
+   */
+  private String m_clusterName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster id
+   */
+  public ServiceService(String clusterName) {
+    m_clusterName = clusterName;
+  }
+
+  /**
+   * Handles URL: /clusters/{clusterID}/services/{serviceID}
+   * Get a specific service.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param serviceName service id
+   * @return service resource representation
+   */
+  @GET
+  @Path("{serviceName}")
+  @Produces("text/plain")
+  public Response getService(@Context HttpHeaders headers, @Context UriInfo ui,
+                             @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, null, ui, org.apache.ambari.server.api.services.Request.Type.GET,
+        createResourceDefinition(serviceName, m_clusterName));
+  }
+
+  /**
+   * Handles URL: /clusters/{clusterId}/services
+   * Get all services for a cluster.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   * @return service collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getServices(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, org.apache.ambari.server.api.services.Request.Type.GET,
+        createResourceDefinition(null, m_clusterName));
+  }
+
+  /**
+   * Handles: PUT /clusters/{clusterId}/services/{serviceId}
+   * Create a specific service.
+   *
+   * @param body        http body
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param serviceName service id
+   * @return information regarding the created service
+   */
+  @PUT
+  @Produces("text/plain")
+  public Response createService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, body, ui, org.apache.ambari.server.api.services.Request.Type.PUT, createResourceDefinition(serviceName, m_clusterName));
+  }
+
+  /**
+   * Handles: POST /clusters/{clusterId}/services/{serviceId}
+   * Update a specific service.
+   *
+   * @param body        http body
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param serviceName service id
+   * @return information regarding the updated service
+   */
+  @POST
+  @Produces("text/plain")
+  public Response updateService(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, body, ui, org.apache.ambari.server.api.services.Request.Type.POST, createResourceDefinition(serviceName, m_clusterName));
+  }
+
+  /**
+   * Handles: DELETE /clusters/{clusterId}/services/{serviceId}
+   * Delete a specific service.
+   *
+   * @param headers     http headers
+   * @param ui          uri info
+   * @param serviceName service id
+   * @return information regarding the deleted service
+   */
+  @DELETE
+  @Produces("text/plain")
+  public Response deleteService(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, null, ui, org.apache.ambari.server.api.services.Request.Type.DELETE, createResourceDefinition(serviceName, m_clusterName));
+  }
+
+  /**
+   * Get the components sub-resource.
+   *
+   * @param serviceName service id
+   * @return the components service
+   */
+  @Path("{serviceName}/components")
+  public ComponentService getComponentHandler(@PathParam("serviceName") String serviceName) {
+
+    return new ComponentService(m_clusterName, serviceName);
+  }
+
+  /**
+   * Create a service resource definition.
+   *
+   * @param serviceName host name
+   * @param clusterName cluster name
+   * @return a service resource definition
+   */
+  ResourceDefinition createResourceDefinition(String serviceName, String clusterName) {
+    return new ServiceResourceDefinition(serviceName, clusterName);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpdatePersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpdatePersistenceManager.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpdatePersistenceManager.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/UpdatePersistenceManager.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,40 @@
+/**
+ * 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.api.services;
+
+
+import org.apache.ambari.server.api.resources.ResourceDefinition;
+import org.apache.ambari.server.AmbariException;
+
+
+/**
+ * Responsible for persisting the updating of a resource in the back end.
+ */
+public class UpdatePersistenceManager extends BasePersistenceManager {
+  @Override
+  public void persist(ResourceDefinition resource) {
+    try {
+      getClusterController().updateResources(resource.getType(), createControllerRequest(resource.getProperties()),
+          resource.getQuery().getPredicate());
+    } catch (AmbariException e) {
+      //todo: handle exception
+      throw new RuntimeException("Update of resource failed: " + e, e);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParser.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParser.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonPropertyParser.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,64 @@
+/**
+ * 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.api.services.parsers;
+
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * JSON parser which parses a JSON string into a map of properties and values.
+ */
+public class JsonPropertyParser implements RequestBodyParser {
+  //todo: change value type to String when it is supported in back end
+  private Map<PropertyId, String> m_properties = new HashMap<PropertyId, String>();
+
+  @Override
+  public Map<PropertyId, String> parse(String s) {
+    ObjectMapper mapper = new ObjectMapper();
+
+    try {
+      processNode(mapper.readValue(s, JsonNode.class), "");
+    } catch (IOException e) {
+      throw new RuntimeException("Unable to parse json: " + e, e);
+    }
+
+    return m_properties;
+  }
+
+  private void processNode(JsonNode node, String path) {
+    Iterator<String> iter = node.getFieldNames();
+    String name;
+    while (iter.hasNext()) {
+      name = iter.next();
+      JsonNode child = node.get(name);
+      if (child.isContainerNode()) {
+        processNode(child, path.isEmpty() ? name : path + '.' + name);
+      } else {
+        m_properties.put(PropertyHelper.getPropertyId(name, path), child.asText());
+      }
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,38 @@
+/**
+ * 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.api.services.parsers;
+
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+import java.util.Map;
+
+/**
+ * Parse the provided String into a map of properties and associated values.
+ */
+public interface RequestBodyParser {
+  /**
+   * Parse the provided string into a map of properties and values.
+   * The key contains both the category hierarchy and the property name.
+   *
+   * @param s  the string body to be parsed
+   *
+   * @return a map of properties or an empty map if no properties exist
+   */
+  public Map<PropertyId, String> parse(String s);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/JsonSerializer.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,140 @@
+/**
+ * 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.api.services.serializers;
+
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.api.util.TreeNode;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.util.DefaultPrettyPrinter;
+
+import javax.ws.rs.core.UriInfo;
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+/**
+ * JSON serializer.
+ * Responsible for representing a result as JSON.
+ */
+public class JsonSerializer implements ResultSerializer {
+
+  /**
+   * Factory used to create JSON generator.
+   */
+  JsonFactory m_factory = new JsonFactory();
+
+  /**
+   * Generator which writes JSON.
+   */
+  JsonGenerator m_generator;
+
+  @Override
+  public Object serialize(Result result, UriInfo uriInfo) {
+    try {
+      ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+      m_generator = createJsonGenerator(bytesOut);
+
+      DefaultPrettyPrinter p = new DefaultPrettyPrinter();
+      p.indentArraysWith(new DefaultPrettyPrinter.Lf2SpacesIndenter());
+      m_generator.setPrettyPrinter(p);
+
+      processNode(result.getResultTree());
+
+      m_generator.close();
+      return bytesOut.toString("UTF-8");
+    } catch (IOException e) {
+      //todo: exception handling
+      throw new RuntimeException("Unable to serialize to json: " + e, e);
+    }
+  }
+
+  private void processNode(TreeNode<Resource> node) throws IOException {
+    String name = node.getName();
+    Resource r = node.getObject();
+
+    if (r == null) {
+      if (name != null) {
+        if (node.getParent() == null) {
+          m_generator.writeStartObject();
+          writeHref(node);
+        }
+        m_generator.writeArrayFieldStart(name);
+      }
+    } else {
+      m_generator.writeStartObject();
+      writeHref(node);
+      // resource props
+      handleResourceProperties(r.getCategories());
+    }
+
+    for (TreeNode<Resource> child : node.getChildren()) {
+      processNode(child);
+    }
+
+    if (r == null) {
+      if (name != null) {
+        m_generator.writeEndArray();
+        if (node.getParent() == null) {
+          m_generator.writeEndObject();
+        }
+      }
+    } else {
+      m_generator.writeEndObject();
+    }
+  }
+
+  private void handleResourceProperties(Map<String, Map<String, String>> mapCatProps) throws IOException {
+    for (Map.Entry<String, Map<String, String>> categoryEntry : mapCatProps.entrySet()) {
+      String category = categoryEntry.getKey();
+      Map<String, String> mapProps = categoryEntry.getValue();
+      if (category != null) {
+        m_generator.writeFieldName(category);
+        m_generator.writeStartObject();
+      }
+
+      for (Map.Entry<String, String> propEntry : mapProps.entrySet()) {
+        m_generator.writeStringField(propEntry.getKey(), propEntry.getValue());
+      }
+
+      if (category != null) {
+        m_generator.writeEndObject();
+      }
+    }
+  }
+
+  private JsonGenerator createJsonGenerator(ByteArrayOutputStream baos) throws IOException {
+    JsonGenerator generator = m_factory.createJsonGenerator(new OutputStreamWriter(baos,
+        Charset.forName("UTF-8").newEncoder()));
+
+    DefaultPrettyPrinter p = new DefaultPrettyPrinter();
+    p.indentArraysWith(new DefaultPrettyPrinter.Lf2SpacesIndenter());
+    generator.setPrettyPrinter(p);
+
+    return generator;
+  }
+
+  private void writeHref(TreeNode<Resource> node) throws IOException {
+    String hrefProp = node.getProperty("href");
+    if (hrefProp != null) {
+      m_generator.writeStringField("href", hrefProp);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/ResultSerializer.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/ResultSerializer.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/ResultSerializer.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/services/serializers/ResultSerializer.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,38 @@
+/**
+ * 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.api.services.serializers;
+
+
+import org.apache.ambari.server.api.services.Result;
+
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Format internal result to format expected by client.
+ */
+public interface ResultSerializer {
+  /**
+   * Serialize the given result to a format expected by client.
+   *
+   * @param result  internal result
+   * @param uriInfo URL info for request
+   * @return the serialized result
+   */
+  Object serialize(Result result, UriInfo uriInfo);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNode.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,101 @@
+/**
+ * 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.api.util;
+
+import java.util.List;
+
+/**
+ * Tree where each node can have a name, properties and an associated object.
+ */
+public interface TreeNode<T> {
+  /**
+   * Obtain the parent node or null if this node is the root.
+   *
+   * @return the parent node or null if this node is the root
+   */
+  public TreeNode<T> getParent();
+
+  /**
+   * Obtain the list of child nodes.
+   *
+   * @return a list of child nodes or an empty list if a leaf node
+   */
+  public List<TreeNode<T>> getChildren();
+
+  /**
+   * Obtain the object associated with this node.
+   *
+   * @return the object associated with this node or null
+   */
+  public T getObject();
+
+  /**
+   * Obtain the name of the node.
+   *
+   * @return the name of the node or null
+   */
+  public String getName();
+
+  /**
+   * Set the name of the node.
+   *
+   * @param name the name to set
+   */
+  public void setName(String name);
+
+  /**
+   * Set the parent node.
+   *
+   * @param parent the parent node to set
+   */
+  public void setParent(TreeNode<T> parent);
+
+  /**
+   * Add a child node for the provided object.
+   *
+   * @param child the object associated with the new child node
+   * @param name  the name of the child node
+   * @return the newly created child node
+   */
+  public TreeNode<T> addChild(T child, String name);
+
+  /**
+   * Add the specified child node.
+   *
+   * @param child the child node to add
+   * @return the added child node
+   */
+  public TreeNode<T> addChild(TreeNode<T> child);
+
+  /**
+   * Set a property on the node.
+   *
+   * @param name  the name of the property
+   * @param value the value of the property
+   */
+  public void setProperty(String name, String value);
+
+  /**
+   * Get the specified node property.
+   *
+   * @param name property name
+   * @return the requested property value or null
+   */
+  public String getProperty(String name);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/api/util/TreeNodeImpl.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,127 @@
+/**
+ * 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.api.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Basic implementation of TreeNode.
+ */
+public class TreeNodeImpl<T> implements TreeNode<T> {
+
+  /**
+   * name of the node
+   */
+  private String m_name;
+
+  /**
+   * parent of the node
+   */
+  private TreeNode<T> m_parent;
+
+  /**
+   * child nodes
+   */
+  private List<TreeNode<T>> m_listChildren = new ArrayList<TreeNode<T>>();
+
+  /**
+   * associated object
+   */
+  private T m_object;
+
+  /**
+   * properties
+   */
+  private Map<String, String> m_mapNodeProps;
+
+  /**
+   * Constructor.
+   *
+   * @param parent parent node
+   * @param object associated object
+   * @param name   node name
+   */
+  public TreeNodeImpl(TreeNode<T> parent, T object, String name) {
+    m_parent = parent;
+    m_object = object;
+    m_name = name;
+  }
+
+  @Override
+  public TreeNode<T> getParent() {
+    return m_parent;
+  }
+
+  @Override
+  public List<TreeNode<T>> getChildren() {
+    return m_listChildren;
+  }
+
+  @Override
+  public T getObject() {
+    return m_object;
+  }
+
+  @Override
+  public void setName(String name) {
+    m_name = name;
+  }
+
+  @Override
+  public String getName() {
+    return m_name;
+  }
+
+  @Override
+  public void setParent(TreeNode<T> parent) {
+    m_parent = parent;
+  }
+
+  @Override
+  public TreeNode<T> addChild(T child, String name) {
+    TreeNodeImpl<T> node = new TreeNodeImpl<T>(this, child, name);
+    m_listChildren.add(node);
+
+    return node;
+  }
+
+  @Override
+  public TreeNode<T> addChild(TreeNode<T> child) {
+    child.setParent(this);
+    m_listChildren.add(child);
+
+    return child;
+  }
+
+  @Override
+  public void setProperty(String name, String value) {
+    if (m_mapNodeProps == null) {
+      m_mapNodeProps = new HashMap<String, String>();
+    }
+    m_mapNodeProps.put(name, value);
+  }
+
+  @Override
+  public String getProperty(String name) {
+    return m_mapNodeProps == null ? null : m_mapNodeProps.get(name);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/ganglia/GangliaHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller.ganglia;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.*;
+
+/**
+ */
+public class GangliaHelper {
+
+  public static List<GangliaMetric> getGangliaProperty(String target,
+                                                       String gangliaCluster,
+                                                       String host,
+                                                       String metric) {
+    String s = "http://" +
+        target +
+        "/ganglia/graph.php" +
+        "?c=" + gangliaCluster +
+        "&h=" + (host == null ? "" : host) +
+        "&m=" + metric +
+        "&json=1";
+
+    try {
+      URLConnection connection = new URL(s).openConnection();
+
+      connection.setDoOutput(true);
+
+      return new ObjectMapper().readValue(connection.getInputStream(),
+          new TypeReference<List<GangliaMetric>>() {
+          });
+
+    } catch (IOException e) {
+      throw new IllegalStateException("Can't get metric " + metric + ".", e);
+    }
+  }
+
+
+  public static List<GangliaMetric> getGangliaMetrics(String target,
+                                                      String gangliaCluster,
+                                                      String host,
+                                                      String metric,
+                                                      Date startTime,
+                                                      Date endTime,
+                                                      long step) {
+    String s = "http://" +
+        target +
+        "/ganglia/graph.php" +
+        "?c=" + gangliaCluster +
+        "&h=" + (host == null ? "" : host) +
+        "&m=" + metric +
+        "&cs=" + startTime.getTime() / 1000 +
+        "&ce=" + endTime.getTime() / 1000 +
+        "&step=" + step +
+        "&json=1";
+
+    try {
+      URLConnection connection = new URL(s).openConnection();
+
+      connection.setDoOutput(true);
+
+      return new ObjectMapper().readValue(connection.getInputStream(),
+          new TypeReference<List<GangliaMetric>>() {
+          });
+
+    } catch (IOException e) {
+      throw new IllegalStateException("Can't get metric " + metric + ".", e);
+    }
+  }
+}