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 [4/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/controller/jdbc/JDBCManagementController.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCManagementController.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCManagementController.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCManagementController.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,673 @@
+/**
+ * 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.jdbc;
+
+import org.apache.ambari.server.controller.internal.PropertyIdImpl;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ClusterRequest;
+import org.apache.ambari.server.controller.ClusterResponse;
+import org.apache.ambari.server.controller.HostRequest;
+import org.apache.ambari.server.controller.HostResponse;
+import org.apache.ambari.server.controller.ServiceComponentHostRequest;
+import org.apache.ambari.server.controller.ServiceComponentHostResponse;
+import org.apache.ambari.server.controller.ServiceComponentRequest;
+import org.apache.ambari.server.controller.ServiceComponentResponse;
+import org.apache.ambari.server.controller.ServiceRequest;
+import org.apache.ambari.server.controller.ServiceResponse;
+import org.apache.ambari.server.controller.TrackActionResponse;
+import org.apache.ambari.server.controller.predicate.AndPredicate;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.EqualsPredicate;
+import org.apache.ambari.server.controller.predicate.PredicateVisitorAcceptor;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Generic JDBC implementation of a management controller.
+ */
+public class JDBCManagementController implements AmbariManagementController {
+  /**
+   * The connection factory.
+   */
+  private final ConnectionFactory connectionFactory;
+
+  /**
+   * Mapping of resource type to the name of the primary table for the resource.
+   */
+  private final Map<Resource.Type, String> resourceTables;
+
+  /**
+   * Primary key mappings.
+   */
+  private final Map<String, Set<PropertyId>> primaryKeys = new HashMap<String, Set<PropertyId>>();
+
+  /**
+   * Key mappings used for joins.
+   */
+  private final Map<String, Map<PropertyId, PropertyId>> importedKeys = new HashMap<String, Map<PropertyId, PropertyId>>();
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct a new JDBC management controller with the given JDBC connection.
+   *
+   * @param connectionFactory  the connection factory
+   */
+  public JDBCManagementController(ConnectionFactory connectionFactory, Map<Resource.Type, String> resourceTables) {
+    this.connectionFactory = connectionFactory;
+    this.resourceTables = resourceTables;
+  }
+
+  // ----- AmbariManagementController ----------------------------------------
+
+  @Override
+  public TrackActionResponse createCluster(ClusterRequest request) throws AmbariException {
+//    createResources(Resource.Type.Cluster, request);
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse createService(ServiceRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse createComponent(ServiceComponentRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse createHost(HostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse createHostComponent(ServiceComponentHostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public Set<ClusterResponse> getClusters(ClusterRequest request) throws AmbariException {
+//    return getResources(Resource.Type.Cluster, request, predicate);
+    return null;
+  }
+
+  @Override
+  public Set<ServiceResponse> getServices(ServiceRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public Set<ServiceComponentResponse> getComponents(ServiceComponentRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public Set<HostResponse> getHosts(HostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public Set<ServiceComponentHostResponse> getHostComponents(ServiceComponentHostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse updateCluster(ClusterRequest request) throws AmbariException {
+//    updateResources(Resource.Type.Cluster, request, predicate);
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse updateService(ServiceRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse updateComponent(ServiceComponentRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse updateHost(HostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse updateHostComponent(ServiceComponentHostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse deleteCluster(ClusterRequest request) throws AmbariException {
+//    deleteResources(Resource.Type.Cluster, predicate);
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse deleteService(ServiceRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse deleteComponent(ServiceComponentRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse deleteHost(HostRequest request) throws AmbariException {
+    return null;
+  }
+
+  @Override
+  public TrackActionResponse deleteHostComponent(ServiceComponentHostRequest request) throws AmbariException {
+    return null;
+  }
+
+
+  // ----- Helper methods ----------------------------------------------------
+
+  /**
+   * Create the resources defined by the properties in the given request object.
+   *
+   * @param type     the resource type
+   * @param request  the request object which defines the set of properties
+   *                 for the resource to be created
+   */
+  private void createResources(Resource.Type type, Request request) {
+    try {
+      Connection connection = connectionFactory.getConnection();
+
+      try {
+
+        Set<Map<PropertyId, String>> propertySet = request.getProperties();
+
+        for (Map<PropertyId, String> properties : propertySet) {
+          String sql = getInsertSQL(resourceTables.get(type), properties);
+
+          Statement statement = connection.createStatement();
+
+          statement.execute(sql);
+        }
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+  /**
+   * Get a set of {@link Resource resources} based on the given request and predicate
+   * information.
+   *
+   * @param type       the resource type
+   * @param request    the request object which defines the desired set of properties
+   * @param predicate  the predicate object which can be used to filter which
+   *                   resources are returned
+   * @return a set of resources based on the given request and predicate information
+   */
+  private Set<Resource> getResources(Resource.Type type, Request request, Predicate predicate) {
+
+    Set<Resource> resources = new HashSet<Resource>();
+    Set<PropertyId> propertyIds = new HashSet<PropertyId>(request.getPropertyIds());
+    if (predicate != null) {
+      propertyIds.addAll(PredicateHelper.getPropertyIds(predicate));
+    }
+
+    try {
+      Connection connection = connectionFactory.getConnection();
+
+      try {
+
+        for (String table : getTables(propertyIds)) {
+          getImportedKeys(connection, table);
+        }
+        String sql = getSelectSQL(propertyIds, predicate);
+        Statement statement = connection.createStatement();
+
+        ResultSet rs = statement.executeQuery(sql);
+        ResultSetMetaData metaData = rs.getMetaData();
+        int columnCount = metaData.getColumnCount();
+
+        while (rs.next()) {
+          final ResourceImpl resource = new ResourceImpl(type);
+          for (int i = 1; i <= columnCount; ++i) {
+            PropertyIdImpl propertyId = new PropertyIdImpl(metaData.getColumnName(i), metaData.getTableName(i), false);
+            if (propertyIds.contains(propertyId)) {
+              resource.setProperty(propertyId, rs.getString(i));
+            }
+          }
+          resources.add(resource);
+        }
+
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+
+    return resources;
+  }
+
+  /**
+   * Update the host resources selected by the given predicate with the properties
+   * from the given request object.
+   *
+   * @param type       the resource type
+   * @param request    the request object which defines the set of properties
+   *                   for the resources to be updated
+   * @param predicate  the predicate object which can be used to filter which
+   *                   host resources are updated
+   */
+  private void updateResources(Resource.Type type, Request request, Predicate predicate) {
+    try {
+      Connection connection = connectionFactory.getConnection();
+      try {
+        Set<Map<PropertyId, String>> propertySet = request.getProperties();
+
+        Map<PropertyId, String> properties = propertySet.iterator().next();
+
+        String resourceTable = resourceTables.get(type);
+
+        predicate = getPredicate(connection, resourceTable, predicate);
+
+        if (predicate == null) {
+          return;
+        }
+
+        String sql = getUpdateSQL(resourceTable, properties, predicate);
+
+        Statement statement = connection.createStatement();
+
+        statement.execute(sql);
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+  /**
+   * Delete the resources selected by the given predicate.
+   *
+   * @param type      the resource type
+   * @param predicate the predicate object which can be used to filter which
+   *                  resources are deleted
+   */
+  private void deleteResources(Resource.Type type, Predicate predicate) {
+    try {
+      Connection connection = connectionFactory.getConnection();
+      try {
+        String resourceTable = resourceTables.get(type);
+
+        predicate = getPredicate(connection, resourceTable, predicate);
+
+        if (predicate == null) {
+          return;
+        }
+
+        String sql = getDeleteSQL(resourceTable, predicate);
+
+        Statement statement = connection.createStatement();
+        statement.execute(sql);
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+  /**
+   * Lazily populate the imported key mappings for the given table.
+   *
+   * @param connection  the connection to use to obtain the database meta data
+   * @param table       the table
+   *
+   * @throws SQLException thrown if the meta data for the given connection cannot be obtained
+   */
+  private void getImportedKeys(Connection connection, String table) throws SQLException {
+    if (!this.importedKeys.containsKey(table)) {
+
+      Map<PropertyId, PropertyId> importedKeys = new HashMap<PropertyId, PropertyId>();
+      this.importedKeys.put(table, importedKeys);
+
+      DatabaseMetaData metaData = connection.getMetaData();
+
+      ResultSet rs = metaData.getImportedKeys(connection.getCatalog(), null, table);
+
+      while (rs.next()) {
+
+        PropertyId pkPropertyId = PropertyHelper.getPropertyId(
+            rs.getString("PKCOLUMN_NAME"), rs.getString("PKTABLE_NAME"));
+
+        PropertyId fkPropertyId = PropertyHelper.getPropertyId(
+            rs.getString("FKCOLUMN_NAME"), rs.getString("FKTABLE_NAME"));
+
+        importedKeys.put(pkPropertyId, fkPropertyId);
+      }
+    }
+  }
+
+  /**
+   * Lazily populate the primary key mappings for the given table.
+   *
+   * @param connection  the connection to use to obtain the database meta data
+   * @param table       the table
+   *
+   * @throws SQLException thrown if the meta data for the given connection cannot be obtained
+   */
+  private void getPrimaryKeys(Connection connection, String table) throws SQLException {
+
+    if (!this.primaryKeys.containsKey(table)) {
+
+      Set<PropertyId> primaryKeys = new HashSet<PropertyId>();
+      this.primaryKeys.put(table, primaryKeys);
+
+      DatabaseMetaData metaData = connection.getMetaData();
+
+      ResultSet rs = metaData.getPrimaryKeys(connection.getCatalog(), null, table);
+
+      while (rs.next()) {
+
+        PropertyId pkPropertyId = PropertyHelper.getPropertyId(
+            rs.getString("COLUMN_NAME"), rs.getString("TABLE_NAME"));
+
+        primaryKeys.add(pkPropertyId);
+      }
+    }
+  }
+
+  /**
+   * Create a new predicate if the given predicate doesn't work for the given table.  Use the
+   * given predicate and join to the given table to get the primary key values to create a new
+   * predicate. (Could probably do this with INNER JOIN???)
+   *
+   * @param connection  the JDBC connection
+   * @param table       the resource table
+   * @param predicate   the predicate
+   *
+   * @return the new predicate
+   *
+   * @throws SQLException thrown if an exception occurred operating on the given connection
+   */
+  private Predicate getPredicate(Connection connection, String table, Predicate predicate) throws SQLException {
+
+    Set<String> predicateTables = getTables(PredicateHelper.getPropertyIds(predicate));
+
+    if (predicateTables.size() > 1 || !predicateTables.contains(table)) {
+      for (String predicateTable : predicateTables){
+        getImportedKeys(connection, predicateTable);
+      }
+
+      getPrimaryKeys(connection, table);
+      getImportedKeys(connection, table);
+
+      Set<PropertyId>   pkPropertyIds = primaryKeys.get(table);
+      String            sql           = getSelectSQL(pkPropertyIds, predicate);
+      Statement         statement     = connection.createStatement();
+      ResultSet         rs            = statement.executeQuery(sql);
+      ResultSetMetaData metaData      = rs.getMetaData();
+      int               columnCount   = metaData.getColumnCount();
+
+      Set<BasePredicate> predicates = new HashSet<BasePredicate>();
+      while (rs.next()) {
+        for (int i = 1; i <= columnCount; ++i) {
+          PropertyIdImpl propertyId = new PropertyIdImpl(metaData.getColumnName(i), metaData.getTableName(i), false);
+          if (pkPropertyIds.contains(propertyId)) {
+            predicates.add(new EqualsPredicate(propertyId, rs.getString(i)));
+          }
+        }
+      }
+
+      predicate = predicates.size() == 0 ? null : predicates.size() > 1 ?
+          new AndPredicate(predicates.toArray(new BasePredicate[2])) :
+          predicates.iterator().next();
+    }
+    return predicate;
+  }
+
+  /**
+   * Get an insert SQL statement based on the given properties.
+   *
+   * @param table      the table
+   * @param properties  the properties
+   *
+   * @return the insert SQL
+   */
+  private String getInsertSQL(String table, Map<PropertyId, String> properties) {
+
+    StringBuilder columns = new StringBuilder();
+    StringBuilder values = new StringBuilder();
+
+    for (Map.Entry<PropertyId, String> entry : properties.entrySet()) {
+      PropertyId propertyId = entry.getKey();
+      Object propertyValue = entry.getValue();
+
+      if (columns.length() > 0) {
+        columns.append(", ");
+      }
+      columns.append(propertyId.getName());
+
+      if (values.length() > 0) {
+        values.append(", ");
+      }
+
+      if (propertyValue instanceof String) {
+        values.append("'");
+        values.append(propertyValue);
+        values.append("'");
+      } else {
+        values.append(propertyValue);
+      }
+    }
+
+    return "insert into " + table + " (" +
+        columns + ") values (" + values + ")";
+  }
+
+  /**
+   * Get a select SQL statement based on the given property ids and predicate.
+   *
+   * @param propertyIds  the property ids
+   * @param predicate    the predicate
+   *
+   * @return the select SQL
+   */
+  private String getSelectSQL(Set<PropertyId> propertyIds, Predicate predicate) {
+
+    StringBuilder columns = new StringBuilder();
+    Set<String> tableSet = new HashSet<String>();
+
+    for (PropertyId propertyId : propertyIds) {
+      if (columns.length() > 0) {
+        columns.append(", ");
+      }
+      columns.append(propertyId.getCategory()).append(".").append(propertyId.getName());
+      tableSet.add(propertyId.getCategory());
+    }
+
+    boolean haveWhereClause = false;
+    StringBuilder whereClause = new StringBuilder();
+    if (predicate != null && predicate instanceof PredicateVisitorAcceptor) {
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      PredicateHelper.visit(predicate, visitor);
+      whereClause.append(visitor.getSQL());
+
+      for (PropertyId propertyId : PredicateHelper.getPropertyIds(predicate)) {
+        tableSet.add(propertyId.getCategory());
+      }
+      haveWhereClause = true;
+    }
+
+    StringBuilder joinClause = new StringBuilder();
+
+    if (tableSet.size() > 1) {
+
+      for (String table : tableSet) {
+        Map<PropertyId, PropertyId> joinKeys = importedKeys.get(table);
+        if (joinKeys != null) {
+          for (Map.Entry<PropertyId, PropertyId> entry : joinKeys.entrySet()) {
+            String category1 = entry.getKey().getCategory();
+            String category2 = entry.getValue().getCategory();
+            if (tableSet.contains(category1) && tableSet.contains(category2)) {
+              if (haveWhereClause) {
+                joinClause.append(" AND ");
+              }
+              joinClause.append(category1).append(".").append(entry.getKey().getName());
+              joinClause.append(" = ");
+              joinClause.append(category2).append(".").append(entry.getValue().getName());
+              tableSet.add(category1);
+              tableSet.add(category2);
+
+              haveWhereClause = true;
+            }
+          }
+        }
+      }
+    }
+
+    StringBuilder tables = new StringBuilder();
+
+    for (String table : tableSet) {
+      if (tables.length() > 0) {
+        tables.append(", ");
+      }
+      tables.append(table);
+    }
+
+    String sql = "select " + columns + " from " + tables;
+
+    if (haveWhereClause) {
+      sql = sql + " where " + whereClause + joinClause;
+    }
+    return sql;
+  }
+
+  /**
+   * Get a delete SQL statement based on the given predicate.
+   *
+   * @param table      the table
+   * @param predicate  the predicate
+   *
+   * @return the delete SQL statement
+   */
+  private String getDeleteSQL(String table, Predicate predicate) {
+
+    StringBuilder whereClause = new StringBuilder();
+    if (predicate instanceof BasePredicate) {
+
+      BasePredicate basePredicate = (BasePredicate) predicate;
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      basePredicate.accept(visitor);
+      whereClause.append(visitor.getSQL());
+
+      return "delete from " + table + " where " + whereClause;
+    }
+    throw new IllegalStateException("Can't generate SQL.");
+  }
+
+  /**
+   * Get an update SQL statement based on the given properties and predicate.
+   *
+   * @param table       the table
+   * @param properties  the properties
+   * @param predicate   the predicate
+   *
+   * @return the update SQL statement
+   */
+  private String getUpdateSQL(String table, Map<PropertyId, String> properties, Predicate predicate) {
+
+    if (predicate instanceof BasePredicate) {
+
+      StringBuilder whereClause = new StringBuilder();
+
+      BasePredicate basePredicate = (BasePredicate) predicate;
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      basePredicate.accept(visitor);
+      whereClause.append(visitor.getSQL());
+
+      StringBuilder setClause = new StringBuilder();
+      for (Map.Entry<PropertyId, String> entry : properties.entrySet()) {
+
+        if (setClause.length() > 0) {
+          setClause.append(", ");
+        }
+        setClause.append(entry.getKey().getName());
+        setClause.append(" = ");
+        Object propertyValue = entry.getValue();
+
+        if (propertyValue instanceof String) {
+          setClause.append("'");
+          setClause.append(propertyValue);
+          setClause.append("'");
+        } else {
+          setClause.append(propertyValue);
+        }
+      }
+
+      return "update " + table + " set " + setClause + " where " + whereClause;
+    }
+    throw new IllegalStateException("Can't generate SQL.");
+  }
+
+  /**
+   * Get the set of tables associated with the given property ids.
+   *
+   * @param propertyIds  the property ids
+   *
+   * @return the set of tables
+   */
+  private static Set<String> getTables(Set<PropertyId> propertyIds) {
+    Set<String> tables = new HashSet<String>();
+    for (PropertyId propertyId : propertyIds) {
+      tables.add(propertyId.getCategory());
+    }
+    return tables;
+  }
+}
+

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCProviderModule.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCProviderModule.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCProviderModule.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCProviderModule.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.controller.jdbc;
+
+import org.apache.ambari.server.controller.spi.ProviderModule;
+import org.apache.ambari.server.controller.utilities.DBHelper;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.controller.spi.PropertyProvider;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class JDBCProviderModule implements ProviderModule {
+
+  private static final List<PropertyProvider> PROPERTY_PROVIDERS = new LinkedList<PropertyProvider>();
+
+  @Override
+  public ResourceProvider getResourceProvider(Resource.Type type) {
+    return new JDBCResourceProvider(DBHelper.CONNECTION_FACTORY, type,
+        PROPERTY_PROVIDERS, PropertyHelper.getPropertyIds(type, "DB"),
+        PropertyHelper.getKeyPropertyIds(type));
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCResourceProvider.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCResourceProvider.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCResourceProvider.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/JDBCResourceProvider.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,420 @@
+/**
+ * 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.jdbc;
+
+import org.apache.ambari.server.controller.internal.PropertyIdImpl;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.internal.SchemaImpl;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.PredicateVisitorAcceptor;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.PropertyProvider;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.spi.Schema;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Generic JDBC based resource provider.
+ */
+public class JDBCResourceProvider implements ResourceProvider {
+
+  private final Resource.Type type;
+
+  private final Set<PropertyId> propertyIds;
+
+  private final ConnectionFactory connectionFactory;
+
+  /**
+   * The list of property providers for this provider's resource type.
+   */
+  private final List<PropertyProvider> propertyProviders;
+
+  /**
+   * The schema for this provider's resource type.
+   */
+  private final Schema schema;
+
+  /**
+   * Key mappings used for joins.
+   */
+  private final Map<String, Map<PropertyId, PropertyId>> importedKeys = new HashMap<String, Map<PropertyId, PropertyId>>();
+
+  public JDBCResourceProvider(ConnectionFactory connectionFactory,
+                              Resource.Type type,
+                              List<PropertyProvider> propertyProviders,
+                              Set<PropertyId> propertyIds,
+                              Map<Resource.Type, PropertyId> keyPropertyIds) {
+    this.connectionFactory = connectionFactory;
+    this.type = type;
+    this.propertyProviders = propertyProviders;
+    this.propertyIds = propertyIds;
+    this.schema = new SchemaImpl(this, keyPropertyIds);
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate) {
+
+    Set<Resource> resources = new HashSet<Resource>();
+    Set<PropertyId> propertyIds = new HashSet<PropertyId>(request.getPropertyIds());
+    if (propertyIds.isEmpty()) {
+      propertyIds.addAll(this.propertyIds);
+    } else {
+      if (predicate != null) {
+        propertyIds.addAll(PredicateHelper.getPropertyIds(predicate));
+      }
+      propertyIds.retainAll(this.propertyIds);
+    }
+
+    try {
+      Connection connection = connectionFactory.getConnection();
+
+      try {
+
+        for (String table : getTables(propertyIds)) {
+          getImportedKeys(connection, table);
+        }
+
+        String sql = getSelectSQL(propertyIds, predicate);
+        Statement statement = connection.createStatement();
+
+        ResultSet rs = statement.executeQuery(sql);
+
+        while (rs.next()) {
+          ResultSetMetaData metaData = rs.getMetaData();
+          int columnCount = metaData.getColumnCount();
+
+          final ResourceImpl resource = new ResourceImpl(type);
+          for (int i = 1; i <= columnCount; ++i) {
+            PropertyIdImpl propertyId = new PropertyIdImpl(metaData.getColumnName(i), metaData.getTableName(i), false);
+            if (propertyIds.contains(propertyId)) {
+              resource.setProperty(propertyId, rs.getString(i));
+            }
+          }
+          resources.add(resource);
+        }
+
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+
+    return resources;
+  }
+
+  @Override
+  public void createResources(Request request) {
+    try {
+      Connection connection = connectionFactory.getConnection();
+
+      try {
+
+        Set<Map<PropertyId, String>> propertySet = request.getProperties();
+
+        for (Map<PropertyId, String> properties : propertySet) {
+          String sql = getInsertSQL(properties);
+
+          Statement statement = connection.createStatement();
+
+          statement.execute(sql);
+        }
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+  @Override
+  public void updateResources(Request request, Predicate predicate) {
+
+    try {
+      Connection connection = connectionFactory.getConnection();
+      try {
+        Set<Map<PropertyId, String>> propertySet = request.getProperties();
+
+        Map<PropertyId, String> properties = propertySet.iterator().next();
+
+        String sql = getUpdateSQL(properties, predicate);
+
+        Statement statement = connection.createStatement();
+
+        statement.execute(sql);
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+  @Override
+  public void deleteResources(Predicate predicate) {
+    try {
+      Connection connection = connectionFactory.getConnection();
+      try {
+        String sql = getDeleteSQL(predicate);
+
+        Statement statement = connection.createStatement();
+        statement.execute(sql);
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("DB error : ", e);
+    }
+  }
+
+
+  private String getInsertSQL(Map<PropertyId, String> properties) {
+
+    StringBuilder columns = new StringBuilder();
+    StringBuilder values = new StringBuilder();
+    String table = null;
+
+
+    for (Map.Entry<PropertyId, String> entry : properties.entrySet()) {
+      PropertyId propertyId    = entry.getKey();
+      String     propertyValue = entry.getValue();
+
+      table = propertyId.getCategory();
+
+
+      if (columns.length() > 0) {
+        columns.append(", ");
+      }
+      columns.append(propertyId.getName());
+
+      if (values.length() > 0) {
+        values.append(", ");
+      }
+      values.append("'");
+      values.append(propertyValue);
+      values.append("'");
+    }
+
+    return "insert into " + table + " (" +
+      columns + ") values (" +values + ")";
+  }
+
+  private String getSelectSQL(Set<PropertyId> propertyIds, Predicate predicate) {
+
+    StringBuilder columns = new StringBuilder();
+    Set<String> tableSet = new HashSet<String>();
+
+    for (PropertyId propertyId : propertyIds) {
+      if (columns.length() > 0) {
+        columns.append(", ");
+      }
+      columns.append(propertyId.getCategory()).append(".").append(propertyId.getName());
+      tableSet.add(propertyId.getCategory());
+    }
+
+
+    boolean haveWhereClause = false;
+    StringBuilder whereClause = new StringBuilder();
+    if (predicate != null &&
+        propertyIds.containsAll(PredicateHelper.getPropertyIds(predicate)) &&
+        predicate instanceof PredicateVisitorAcceptor) {
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      ((PredicateVisitorAcceptor) predicate).accept(visitor);
+      whereClause.append(visitor.getSQL());
+      haveWhereClause = true;
+    }
+
+    StringBuilder joinClause = new StringBuilder();
+
+    if (tableSet.size() > 1) {
+
+      for (String table : tableSet) {
+        Map<PropertyId, PropertyId> joinKeys = importedKeys.get(table);
+        if (joinKeys != null) {
+          for (Map.Entry<PropertyId, PropertyId> entry : joinKeys.entrySet()) {
+            String category1 = entry.getKey().getCategory();
+            String category2 = entry.getValue().getCategory();
+            if (tableSet.contains(category1) && tableSet.contains(category2)) {
+              if (haveWhereClause) {
+                joinClause.append(" AND ");
+              }
+              joinClause.append(category1).append(".").append(entry.getKey().getName());
+              joinClause.append(" = ");
+              joinClause.append(category2).append(".").append(entry.getValue().getName());
+              tableSet.add(category1);
+              tableSet.add(category2);
+
+              haveWhereClause = true;
+            }
+          }
+        }
+      }
+    }
+
+    StringBuilder tables = new StringBuilder();
+
+    for (String table : tableSet) {
+      if (tables.length() > 0) {
+        tables.append(", ");
+      }
+      tables.append(table);
+    }
+
+    String sql = "select " + columns + " from " + tables;
+
+    if (haveWhereClause) {
+      sql = sql + " where " + whereClause + joinClause;
+    }
+
+    return sql;
+  }
+
+  private String getDeleteSQL(Predicate predicate) {
+
+    StringBuilder whereClause = new StringBuilder();
+    if (predicate instanceof BasePredicate) {
+
+      BasePredicate basePredicate = (BasePredicate) predicate;
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      basePredicate.accept(visitor);
+      whereClause.append(visitor.getSQL());
+
+      String table = basePredicate.getPropertyIds().iterator().next().getCategory();
+
+      return "delete from " + table + " where " + whereClause;
+    }
+    throw new IllegalStateException("Can't generate SQL.");
+  }
+
+  private String getUpdateSQL(Map<PropertyId, String> properties, Predicate predicate) {
+
+    if (predicate instanceof BasePredicate) {
+
+      StringBuilder whereClause = new StringBuilder();
+
+      BasePredicate basePredicate = (BasePredicate) predicate;
+
+      SQLPredicateVisitor visitor = new SQLPredicateVisitor();
+      basePredicate.accept(visitor);
+      whereClause.append(visitor.getSQL());
+
+      String table = basePredicate.getPropertyIds().iterator().next().getCategory();
+
+
+      StringBuilder setClause = new StringBuilder();
+      for (Map.Entry<PropertyId, String> entry : properties.entrySet()) {
+
+        if (setClause.length() > 0) {
+          setClause.append(", ");
+        }
+        setClause.append(entry.getKey().getName());
+        setClause.append(" = ");
+        setClause.append("'");
+        setClause.append(entry.getValue());
+        setClause.append("'");
+      }
+
+      return "update " + table + " set " + setClause + " where " + whereClause;
+    }
+    throw new IllegalStateException("Can't generate SQL.");
+  }
+
+  @Override
+  public Set<PropertyId> getPropertyIds() {
+    return propertyIds;
+  }
+
+  @Override
+  public List<PropertyProvider> getPropertyProviders() {
+    return propertyProviders;
+  }
+
+  @Override
+  public Schema getSchema() {
+    return schema;
+  }
+
+  /**
+   * Lazily populate the imported key mappings for the given table.
+   *
+   * @param connection  the connection to use to obtain the database meta data
+   * @param table       the table
+   *
+   * @throws SQLException thrown if the meta data for the given connection cannot be obtained
+   */
+  private void getImportedKeys(Connection connection, String table) throws SQLException {
+    if (!this.importedKeys.containsKey(table)) {
+
+      Map<PropertyId, PropertyId> importedKeys = new HashMap<PropertyId, PropertyId>();
+      this.importedKeys.put(table, importedKeys);
+
+      DatabaseMetaData metaData = connection.getMetaData();
+
+      ResultSet rs = metaData.getImportedKeys(connection.getCatalog(), null, table);
+
+      while (rs.next()) {
+
+        PropertyId pkPropertyId = PropertyHelper.getPropertyId(
+            rs.getString("PKCOLUMN_NAME"), rs.getString("PKTABLE_NAME"));
+
+        PropertyId fkPropertyId = PropertyHelper.getPropertyId(
+            rs.getString("FKCOLUMN_NAME"), rs.getString("FKTABLE_NAME"));
+
+        importedKeys.put(pkPropertyId, fkPropertyId);
+      }
+    }
+  }
+
+  /**
+   * Get the set of tables associated with the given property ids.
+   *
+   * @param propertyIds  the property ids
+   *
+   * @return the set of tables
+   */
+  private static Set<String> getTables(Set<PropertyId> propertyIds) {
+    Set<String> tables = new HashSet<String>();
+    for (PropertyId propertyId : propertyIds) {
+      tables.add(propertyId.getCategory());
+    }
+    return tables;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLPredicateVisitor.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLPredicateVisitor.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLPredicateVisitor.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLPredicateVisitor.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,85 @@
+/**
+ * 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.jdbc;
+
+import org.apache.ambari.server.controller.predicate.ArrayPredicate;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.ComparisonPredicate;
+import org.apache.ambari.server.controller.predicate.PredicateVisitor;
+import org.apache.ambari.server.controller.predicate.UnaryPredicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+/**
+ * Predicate visitor used to generate a SQL where clause from a predicate graph.
+ */
+public class SQLPredicateVisitor implements PredicateVisitor {
+
+  /**
+   * The string builder.
+   */
+  private final StringBuilder stringBuilder = new StringBuilder();
+
+
+  // ----- PredicateVisitor --------------------------------------------------
+
+  @Override
+  public void acceptComparisonPredicate(ComparisonPredicate predicate) {
+    PropertyId propertyId = predicate.getPropertyId();
+
+    if (propertyId.getCategory() != null) {
+      stringBuilder.append(propertyId.getCategory()).append(".");
+    }
+    stringBuilder.append(propertyId.getName());
+
+    stringBuilder.append(" ").append(predicate.getOperator()).append(" \"");
+    stringBuilder.append(predicate.getValue());
+    stringBuilder.append("\"");
+
+  }
+
+  @Override
+  public void acceptArrayPredicate(ArrayPredicate predicate) {
+    BasePredicate[] predicates = predicate.getPredicates();
+    if (predicates.length > 0) {
+
+      stringBuilder.append("(");
+      for (int i = 0; i < predicates.length; i++) {
+        if (i > 0) {
+          stringBuilder.append(" ").append(predicate.getOperator()).append(" ");
+        }
+        predicates[i].accept(this);
+      }
+      stringBuilder.append(")");
+    }
+  }
+
+  @Override
+  public void acceptUnaryPredicate(UnaryPredicate predicate) {
+    stringBuilder.append(predicate.getOperator()).append("(");
+    predicate.getPredicate().accept(this);
+    stringBuilder.append(")");
+  }
+
+
+  // ----- SQLPredicateVisitor -----------------------------------------------
+
+  public String getSQL() {
+    return stringBuilder.toString();
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLiteConnectionFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLiteConnectionFactory.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLiteConnectionFactory.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jdbc/SQLiteConnectionFactory.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.controller.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Connection factory implementation for SQLite.
+ */
+public class SQLiteConnectionFactory implements ConnectionFactory {
+
+  /**
+   * The connection URL minus the db file.
+   */
+  private static final String CONNECTION_URL = "jdbc:sqlite:";
+
+  /**
+   * The filename of the SQLite db file.
+   */
+  private final String dbFile;
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Create a connection factory.
+   *
+   * @param dbFile  the SQLite DB filename
+   */
+  public SQLiteConnectionFactory(String dbFile) {
+    this.dbFile = dbFile;
+    try {
+      Class.forName("org.sqlite.JDBC");
+    } catch (ClassNotFoundException e) {
+      throw new IllegalStateException("Can't load SQLite.", e);
+    }
+  }
+
+
+  // ----- ConnectionFactory -------------------------------------------------
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return DriverManager.getConnection(CONNECTION_URL + dbFile);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,46 @@
+/**
+ * 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.jmx;
+
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ *
+ */
+public class JMXHelper {
+
+  public static JMXMetrics getJMXMetrics(String target, String bean) {
+    String s = "http://" + target + "/jmx?qry=" + (bean == null ? "Hadoop:*" : bean);
+    try {
+      URLConnection connection = new URL(s).openConnection();
+
+      connection.setDoOutput(true);
+
+      return new ObjectMapper().readValue(connection.getInputStream(),
+          JMXMetrics.class);
+
+    } catch (IOException e) {
+      throw new IllegalStateException("Can't get metric " + ".", e);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetrics.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetrics.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetrics.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXMetrics.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,50 @@
+/**
+ * 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.jmx;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class JMXMetrics {
+
+  private List<Map<String, String>> beans;
+
+  public List<Map<String, String>> getBeans() {
+    return beans;
+  }
+
+  public void setBeans(List<Map<String, String>> beans) {
+    this.beans = beans;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder stringBuilder = new StringBuilder();
+
+    for (Map<String, String> map : beans) {
+      for (Map.Entry<String, String> entry : map.entrySet()) {
+        stringBuilder.append("    " + entry.toString() + "\n");
+      }
+    }
+    return stringBuilder.toString();
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXPropertyProvider.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXPropertyProvider.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXPropertyProvider.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/jmx/JMXPropertyProvider.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,132 @@
+/**
+ * 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.jmx;
+
+import org.apache.ambari.server.controller.internal.PropertyIdImpl;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.PropertyProvider;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Property provider implementation for JMX sources.
+ */
+public class JMXPropertyProvider implements PropertyProvider {
+
+  /**
+   * Map of property ids supported by this provider.
+   */
+  private final Set<PropertyId> propertyIds;
+
+  private final Map<String, String> hosts;
+
+  private static final Map<String, String> JMX_PORTS = new HashMap<String, String>();
+
+  static {
+    JMX_PORTS.put("NAMENODE", "50070");
+    JMX_PORTS.put("HBASE_MASTER", "60010");
+    JMX_PORTS.put("JOBTRACKER", "50030");
+    JMX_PORTS.put("DATANODE", "50075");
+    JMX_PORTS.put("TASKTRACKER", "50060");
+  }
+
+  private JMXPropertyProvider(Resource.Type type, Map<String, String> hosts) {
+    this.hosts = hosts;
+    this.propertyIds = PropertyHelper.getPropertyIds(type, "JMX");
+  }
+
+  @Override
+  public Set<Resource> populateResources(Set<Resource> resources, Request request, Predicate predicate) {
+    Set<Resource> keepers = new HashSet<Resource>();
+    for (Resource resource : resources) {
+      if (populateResource(resource, request, predicate)) {
+        keepers.add(resource);
+      }
+    }
+    return keepers;
+  }
+
+  @Override
+  public Set<PropertyId> getPropertyIds() {
+    return propertyIds;
+  }
+
+
+  private boolean populateResource(Resource resource, Request request, Predicate predicate) {
+
+    if (getPropertyIds().isEmpty()) {
+      return true;
+    }
+
+    Set<PropertyId> ids = new HashSet<PropertyId>(request.getPropertyIds());
+    if (ids == null || ids.isEmpty()) {
+      ids = getPropertyIds();
+    } else {
+      if (predicate != null) {
+        ids.addAll(PredicateHelper.getPropertyIds(predicate));
+      }
+      ids.retainAll(getPropertyIds());
+    }
+
+    String hostName = hosts.get(resource.getPropertyValue(new PropertyIdImpl("host_name", "HostRoles", false)));
+    String port = JMX_PORTS.get(resource.getPropertyValue(new PropertyIdImpl("component_name", "HostRoles", false)));
+
+    String jmxSource = hostName + ":" + port;
+
+    if (hostName == null || port == null || jmxSource == null) {
+      return true;
+    }
+
+    JMXMetrics metrics = JMXHelper.getJMXMetrics(jmxSource, null);
+
+    for (Map<String, String> propertyMap : metrics.getBeans()) {
+      String category = propertyMap.get("tag.context");
+      if (category != null) {
+        for (Map.Entry<String, String> entry : propertyMap.entrySet()) {
+          String name = entry.getKey();
+
+          PropertyIdImpl propertyId = new PropertyIdImpl(name, category, false);
+
+          if (ids.contains(propertyId)) {
+            resource.setProperty(propertyId, entry.getValue());
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Factory method.
+   *
+   * @param type the {@link Resource.Type resource type}
+   * @return a new {@link PropertyProvider} instance
+   */
+  public static PropertyProvider create(Resource.Type type, Map<String, String> hosts) {
+    return new JMXPropertyProvider(type, hosts);
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ProviderModule.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ProviderModule.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ProviderModule.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/ProviderModule.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.controller.spi;
+
+/**
+ *  Interface to allow the plugging in of resource adapters.
+ */
+public interface ProviderModule {
+  /**
+   * Get a resource adapter for the given resource type.
+   *
+   * @param type  the resource type
+   *
+   * @return the resource adapter
+   */
+  public ResourceProvider getResourceProvider(Resource.Type type);
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/ClusterControllerHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/ClusterControllerHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/ClusterControllerHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/ClusterControllerHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,48 @@
+/**
+ * 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.utilities;
+
+import org.apache.ambari.server.controller.spi.ProviderModule;
+import org.apache.ambari.server.controller.internal.ClusterControllerImpl;
+import org.apache.ambari.server.controller.spi.ClusterController;
+
+/**
+ * Temporary class to bootstrap a cluster controller.  TODO : Replace this global state with injection.
+ */
+public class ClusterControllerHelper {
+
+  private static String PROVIDER_MODULE_CLASS = System.getProperty("provider.module.class",
+      "org.apache.ambari.server.controller.internal.DefaultProviderModule");
+
+  private static ClusterController controller;
+
+  public static synchronized ClusterController getClusterController() {
+    if (controller == null) {
+      try {
+        Class implClass = Class.forName(PROVIDER_MODULE_CLASS);
+        ProviderModule providerModule = (ProviderModule) implClass.newInstance();
+        return new ClusterControllerImpl(providerModule);
+
+      } catch (Exception e) {
+        throw new IllegalStateException("Can't create provider module " + PROVIDER_MODULE_CLASS);
+      }
+    }
+    return controller;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/DBHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/DBHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/DBHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/DBHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,86 @@
+/**
+ * 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.utilities;
+
+import org.apache.ambari.server.controller.jdbc.ConnectionFactory;
+import org.apache.ambari.server.controller.jdbc.SQLiteConnectionFactory;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+public class DBHelper {
+  private static String DB_FILE_NAME = System.getProperty("ambariapi.dbfile", "src/test/resources/data.db");
+
+  public static final ConnectionFactory CONNECTION_FACTORY = new SQLiteConnectionFactory(DB_FILE_NAME);
+
+  private static final Map<String, String> HOSTS = readHosts();
+
+  public static Map<String, String> getHosts() {
+    return HOSTS;
+  }
+
+  private static Map<String, String> readHosts() {
+    Map<String, String> hosts = new HashMap<String, String>();
+
+    try {
+      Connection connection = CONNECTION_FACTORY.getConnection();
+
+      try {
+        String sql = "select attributes from hosts";
+
+        Statement statement = connection.createStatement();
+
+        ResultSet rs = statement.executeQuery(sql);
+
+        ObjectMapper mapper = new ObjectMapper();
+
+        while (rs.next()) {
+          String attributes = rs.getString(1);
+
+          if (!attributes.startsWith("[]")) {
+            try {
+              Map<String, String> attributeMap = mapper.readValue(attributes, new TypeReference<Map<String, String>>() {
+              });
+              hosts.put(attributeMap.get("privateFQDN"), attributeMap.get("publicFQDN"));
+            } catch (IOException e) {
+              throw new IllegalStateException("Can't read hosts " + attributes, e);
+            }
+          }
+        }
+
+      } finally {
+        connection.close();
+      }
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("Can't access DB.", e);
+    }
+
+    return hosts;
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateBuilder.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateBuilder.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateBuilder.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateBuilder.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,315 @@
+/**
+ * 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.utilities;
+
+import org.apache.ambari.server.controller.internal.PropertyIdImpl;
+import org.apache.ambari.server.controller.predicate.AndPredicate;
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.Comparables;
+import org.apache.ambari.server.controller.predicate.EqualsPredicate;
+import org.apache.ambari.server.controller.predicate.GreaterEqualsPredicate;
+import org.apache.ambari.server.controller.predicate.GreaterPredicate;
+import org.apache.ambari.server.controller.predicate.LessEqualsPredicate;
+import org.apache.ambari.server.controller.predicate.LessPredicate;
+import org.apache.ambari.server.controller.predicate.NotPredicate;
+import org.apache.ambari.server.controller.predicate.OrPredicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Builder for predicates.
+ */
+public class PredicateBuilder {
+
+  private PropertyId propertyId;
+  private List<BasePredicate> predicates = new LinkedList<BasePredicate>();
+  private Operator operator = null;
+  private final PredicateBuilder outer;
+  private boolean done = false;
+  private boolean not = false;
+
+  public PredicateBuilder() {
+    this.outer = null;
+  }
+
+  private PredicateBuilder(PredicateBuilder outer) {
+    this.outer = outer;
+  }
+
+  private enum Operator {
+    And,
+    Or
+  }
+
+
+  public PredicateBuilderWithProperty property(String property, String category, boolean temporal) {
+    return property(new PropertyIdImpl(property, category, temporal));
+  }
+
+  public PredicateBuilderWithProperty property(String property, String category) {
+    return property(property, category, false);
+  }
+
+  public PredicateBuilderWithProperty property(String property) {
+    return property(property, null);
+  }
+
+  public PredicateBuilderWithProperty property(PropertyId id) {
+    checkDone();
+    propertyId = id;
+    return new PredicateBuilderWithProperty();
+  }
+
+  public PredicateBuilder not() {
+    not = true;
+    return this;
+  }
+
+
+  public PredicateBuilder begin() {
+    checkDone();
+    return new PredicateBuilder(this);
+  }
+
+  public BasePredicate toPredicate() {
+    return getPredicate();
+  }
+
+  private void checkDone() {
+    if (done) {
+      throw new IllegalStateException("Can't reuse a predicate builder.");
+    }
+  }
+
+  private PredicateBuilderWithPredicate getPredicateBuilderWithPredicate() {
+    return new PredicateBuilderWithPredicate();
+  }
+
+  private void addPredicate(BasePredicate predicate) {
+    predicates.add(predicate);
+  }
+
+  private void handleComparator() {
+    if (operator == null) {
+      return;
+    }
+
+    if (predicates.size() == 0) {
+      throw new IllegalStateException("No left operand.");
+    }
+    BasePredicate predicate;
+
+    switch (operator) {
+      case And:
+        predicate = new AndPredicate(predicates.toArray(new BasePredicate[predicates.size()]));
+        break;
+      case Or:
+        predicate = new OrPredicate(predicates.toArray(new BasePredicate[predicates.size()]));
+        break;
+      default:
+        throw new IllegalStateException("Unknown operator " + this.operator);
+    }
+    predicates.clear();
+    addPredicate(predicate);
+  }
+
+  private BasePredicate getPredicate() {
+    handleComparator();
+
+    if (predicates.size() == 1) {
+      BasePredicate predicate = predicates.get(0);
+      if (not) {
+        predicate = new NotPredicate(predicate);
+        not = false;
+      }
+      return predicate;
+    }
+    throw new IllegalStateException("Can't return a predicate.");
+  }
+
+  public class PredicateBuilderWithProperty {
+
+    // ----- Equals -----
+    public PredicateBuilderWithPredicate equals(Comparable<String> value) {
+      if (propertyId == null) {
+        throw new IllegalStateException("No property.");
+      }
+      addPredicate(new EqualsPredicate(propertyId, value));
+
+      return new PredicateBuilderWithPredicate();
+    }
+
+    public PredicateBuilderWithPredicate equals(Integer value) {
+      return equals(Comparables.forInteger(value));
+    }
+
+    public PredicateBuilderWithPredicate equals(Float value) {
+      return equals(Comparables.forFloat(value));
+    }
+
+    public PredicateBuilderWithPredicate equals(Double value) {
+      return equals(Comparables.forDouble(value));
+    }
+
+    public PredicateBuilderWithPredicate equals(Long value) {
+      return equals(Comparables.forLong(value));
+    }
+
+    // ----- Greater than -----
+    public PredicateBuilderWithPredicate greaterThan(Comparable<String> value) {
+      if (propertyId == null) {
+        throw new IllegalStateException("No property.");
+      }
+      addPredicate(new GreaterPredicate(propertyId, value));
+
+      return new PredicateBuilderWithPredicate();
+    }
+
+    public PredicateBuilderWithPredicate greaterThan(Integer value) {
+      return greaterThan(Comparables.forInteger(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThan(Float value) {
+      return greaterThan(Comparables.forFloat(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThan(Double value) {
+      return greaterThan(Comparables.forDouble(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThan(Long value) {
+      return greaterThan(Comparables.forLong(value));
+    }
+
+    // ----- Greater than equal to -----
+    public PredicateBuilderWithPredicate greaterThanEqualTo(Comparable<String> value) {
+      if (propertyId == null) {
+        throw new IllegalStateException("No property.");
+      }
+      addPredicate(new GreaterEqualsPredicate(propertyId, value));
+
+      return new PredicateBuilderWithPredicate();
+    }
+
+    public PredicateBuilderWithPredicate greaterThanEqualTo(Integer value) {
+      return greaterThanEqualTo(Comparables.forInteger(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThanEqualTo(Float value) {
+      return greaterThanEqualTo(Comparables.forFloat(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThanEqualTo(Double value) {
+      return greaterThanEqualTo(Comparables.forDouble(value));
+    }
+
+    public PredicateBuilderWithPredicate greaterThanEqualTo(Long value) {
+      return greaterThanEqualTo(Comparables.forLong(value));
+    }
+
+    // ----- Less than -----
+    public PredicateBuilderWithPredicate lessThan(Comparable<String> value) {
+      if (propertyId == null) {
+        throw new IllegalStateException("No property.");
+      }
+      addPredicate(new LessPredicate(propertyId, value));
+
+      return new PredicateBuilderWithPredicate();
+    }
+
+    public PredicateBuilderWithPredicate lessThan(Integer value) {
+      return lessThan(Comparables.forInteger(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThan(Float value) {
+      return lessThan(Comparables.forFloat(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThan(Double value) {
+      return lessThan(Comparables.forDouble(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThan(Long value) {
+      return lessThan(Comparables.forLong(value));
+    }
+
+    // ----- Less than equal to -----
+    public PredicateBuilderWithPredicate lessThanEqualTo(Comparable<String> value) {
+      if (propertyId == null) {
+        throw new IllegalStateException("No property.");
+      }
+      addPredicate(new LessEqualsPredicate(propertyId, value));
+
+      return new PredicateBuilderWithPredicate();
+    }
+
+    public PredicateBuilderWithPredicate lessThanEqualTo(Integer value) {
+      return lessThanEqualTo(Comparables.forInteger(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThanEqualTo(Float value) {
+      return lessThanEqualTo(Comparables.forFloat(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThanEqualTo(Double value) {
+      return lessThanEqualTo(Comparables.forDouble(value));
+    }
+
+    public PredicateBuilderWithPredicate lessThanEqualTo(Long value) {
+      return lessThanEqualTo(Comparables.forLong(value));
+    }
+  }
+
+  public class PredicateBuilderWithPredicate {
+    public PredicateBuilder and() {
+
+      if (operator != Operator.And) {
+        handleComparator();
+        operator = Operator.And;
+      }
+      return PredicateBuilder.this;
+    }
+
+    public PredicateBuilder or() {
+
+      if (operator != Operator.Or) {
+        handleComparator();
+        operator = Operator.Or;
+      }
+      return PredicateBuilder.this;
+    }
+
+    public BasePredicate toPredicate() {
+      if (outer != null) {
+        throw new IllegalStateException("Unbalanced block - missing end.");
+      }
+      done = true;
+      return getPredicate();
+    }
+
+    public PredicateBuilderWithPredicate end() {
+      if (outer == null) {
+        throw new IllegalStateException("Unbalanced block - missing begin.");
+      }
+      outer.addPredicate(getPredicate());
+      return outer.getPredicateBuilderWithPredicate();
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PredicateHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,46 @@
+/**
+ * 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.utilities;
+
+import org.apache.ambari.server.controller.predicate.BasePredicate;
+import org.apache.ambari.server.controller.predicate.PredicateVisitor;
+import org.apache.ambari.server.controller.predicate.PredicateVisitorAcceptor;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.PropertyId;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ *
+ */
+public class PredicateHelper {
+
+  public static Set<PropertyId> getPropertyIds(Predicate predicate) {
+    if (predicate instanceof BasePredicate) {
+      return ((BasePredicate) predicate).getPropertyIds();
+    }
+    return Collections.emptySet();
+  }
+
+  public static void visit(Predicate predicate, PredicateVisitor visitor) {
+    if (predicate instanceof PredicateVisitorAcceptor) {
+      ((PredicateVisitorAcceptor) predicate).accept(visitor);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java Tue Oct  9 17:01:58 2012
@@ -0,0 +1,132 @@
+/**
+ * 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.utilities;
+
+import org.apache.ambari.server.controller.internal.PropertyIdImpl;
+import org.apache.ambari.server.controller.internal.RequestImpl;
+import org.apache.ambari.server.controller.spi.PropertyId;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ */
+public class PropertyHelper {
+
+  private static final String PROPERTIES_FILE = "properties.json";
+  private static final String KEY_PROPERTIES_FILE = "key_properties.json";
+
+  private static final Map<Resource.Type, Map<String, Set<PropertyId>>> PROPERTY_IDS = readPropertyIds(PROPERTIES_FILE);
+  private static final Map<Resource.Type, Map<Resource.Type, PropertyId>> KEY_PROPERTY_IDS = readKeyPropertyIds(KEY_PROPERTIES_FILE);
+
+  public static PropertyId getPropertyId(String name, String category) {
+    return new PropertyIdImpl(name, category, false);
+  }
+
+  public static PropertyId getPropertyId(String name, String category, boolean temporal) {
+    return new PropertyIdImpl(name, category, temporal);
+  }
+
+  public static Set<PropertyId> getPropertyIds(Resource.Type resourceType, String providerKey) {
+
+    Map<String, Set<PropertyId>> propertyIds = PROPERTY_IDS.get(resourceType);
+    if (propertyIds != null) {
+      return propertyIds.get(providerKey);
+    }
+    return Collections.emptySet();
+  }
+
+  public static Map<Resource.Type, PropertyId> getKeyPropertyIds(Resource.Type resourceType) {
+    return KEY_PROPERTY_IDS.get(resourceType);
+  }
+
+  public static Map<PropertyId, String> getProperties(Resource resource) {
+    Map<PropertyId, String> properties = new HashMap<PropertyId, String>();
+
+    Map<String, Map<String, String>> categories = resource.getCategories();
+
+    for (Map.Entry<String, Map<String, String>> categoryEntry : categories.entrySet()) {
+      for (Map.Entry<String, String>  propertyEntry : categoryEntry.getValue().entrySet()) {
+
+        properties.put(PropertyHelper.getPropertyId(propertyEntry.getKey(), categoryEntry.getKey()), propertyEntry.getValue());
+      }
+    }
+    return properties;
+  }
+
+  /**
+   * Factory method to create a create request from the given set of property maps.
+   * Each map contains the properties to be used to create a resource.  Multiple maps in the
+   * set should result in multiple creates.
+   *
+   * @param properties   the properties associated with the request; may be null
+   */
+  public static Request getCreateRequest(Set<Map<PropertyId, String>> properties) {
+    return new RequestImpl(null,  properties);
+  }
+
+  /**
+   * Factory method to create a read request from the given set of property ids.  The set of
+   * property ids represents the properties of interest for the query.
+   *
+   * @param propertyIds  the property ids associated with the request; may be null
+   */
+  public static Request getReadRequest(Set<PropertyId> propertyIds) {
+    return new RequestImpl(propertyIds,  null);
+  }
+
+  /**
+   * Factory method to create an update request from the given map of properties.
+   * The properties values in the given map are used to update the resource.
+   *
+   * @param properties   the properties associated with the request; may be null
+   */
+  public static Request getUpdateRequest(Map<PropertyId, String> properties) {
+    return new RequestImpl(null,  Collections.singleton(properties));
+  }
+
+  private static Map<Resource.Type, Map<String, Set<PropertyId>>> readPropertyIds(String filename) {
+    ObjectMapper mapper = new ObjectMapper();
+
+    try {
+      return mapper.readValue(ClassLoader.getSystemResourceAsStream(filename), new TypeReference<Map<Resource.Type, Map<String, Set<PropertyIdImpl>>>>() {
+      });
+    } catch (IOException e) {
+      throw new IllegalStateException("Can't read properties file " + filename, e);
+    }
+  }
+
+  private static Map<Resource.Type, Map<Resource.Type, PropertyId>> readKeyPropertyIds(String filename) {
+    ObjectMapper mapper = new ObjectMapper();
+
+    try {
+      return mapper.readValue(ClassLoader.getSystemResourceAsStream(filename), new TypeReference<Map<Resource.Type, Map<Resource.Type, PropertyIdImpl>>>() {
+      });
+    } catch (IOException e) {
+      throw new IllegalStateException("Can't read properties file " + filename, e);
+    }
+  }
+}

Added: incubator/ambari/branches/AMBARI-666/ambari-server/src/main/resources/key_properties.json
URL: http://svn.apache.org/viewvc/incubator/ambari/branches/AMBARI-666/ambari-server/src/main/resources/key_properties.json?rev=1396109&view=auto
==============================================================================
--- incubator/ambari/branches/AMBARI-666/ambari-server/src/main/resources/key_properties.json (added)
+++ incubator/ambari/branches/AMBARI-666/ambari-server/src/main/resources/key_properties.json Tue Oct  9 17:01:58 2012
@@ -0,0 +1,67 @@
+{
+  "Cluster":{
+    "Cluster":{
+      "name":"cluster_name",
+      "category":"Clusters",
+      "temporal":false
+    }
+  },
+  "Service":{
+    "Cluster":{
+      "name":"cluster_name",
+      "category":"ServiceInfo",
+      "temporal":false
+    },
+    "Service":{
+      "name":"service_name",
+      "category":"ServiceInfo",
+      "temporal":false
+    }
+  },
+  "Host":{
+    "Cluster":{
+      "name":"cluster_name",
+      "category":"Hosts",
+      "temporal":false
+    },
+    "Host":{
+      "name":"host_name",
+      "category":"Hosts",
+      "temporal":false
+    }
+  },
+  "Component":{
+    "Cluster":{
+      "name":"cluster_name",
+      "category":"ServiceComponentInfo",
+      "temporal":false
+    },
+    "Service":{
+      "name":"service_name",
+      "category":"ServiceComponentInfo",
+      "temporal":false
+    },
+    "Component":{
+      "name":"component_name",
+      "category":"ServiceComponentInfo",
+      "temporal":false
+    }
+  },
+  "HostComponent":{
+    "Cluster":{
+      "name":"cluster_name",
+      "category":"HostRoles",
+      "temporal":false
+    },
+    "Host":{
+      "name":"host_name",
+      "category":"HostRoles",
+      "temporal":false
+    },
+    "HostComponent":{
+      "name":"component_name",
+      "category":"HostRoles",
+      "temporal":false
+    }
+  }
+}