You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ni...@apache.org on 2017/01/03 11:43:17 UTC

[12/20] ambari git commit: AMBARI-19321 : Hive View 2.0 - Minimal view for Hive which includes new UI changes. Also made changes in poms as required (nitirajrathore)

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/ATSRequestsDelegateImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/ATSRequestsDelegateImpl.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/ATSRequestsDelegateImpl.java
new file mode 100644
index 0000000..a2c9396
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/ATSRequestsDelegateImpl.java
@@ -0,0 +1,175 @@
+/**
+ * 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.view.hive20.resources.jobs.atsJobs;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.commons.io.IOUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+public class ATSRequestsDelegateImpl implements ATSRequestsDelegate {
+  protected final static Logger LOG =
+    LoggerFactory.getLogger(ATSRequestsDelegateImpl.class);
+  public static final String EMPTY_ENTITIES_JSON = "{ \"entities\" : [  ] }";
+
+  private ViewContext context;
+  private String atsUrl;
+
+  public ATSRequestsDelegateImpl(ViewContext context, String atsUrl) {
+    this.context = context;
+    this.atsUrl = addProtocolIfMissing(atsUrl);
+  }
+
+  private String addProtocolIfMissing(String atsUrl) {
+    if (!atsUrl.matches("^[^:]+://.*$"))
+      atsUrl = "http://" + atsUrl;
+    return atsUrl;
+  }
+
+  @Override
+  public String hiveQueryIdDirectUrl(String entity) {
+    return atsUrl + "/ws/v1/timeline/HIVE_QUERY_ID/" + entity;
+  }
+
+  @Override
+  public String hiveQueryIdOperationIdUrl(String operationId) {
+    // ATS parses operationId started with digit as integer and not returns the response.
+    // Quotation prevents this.
+    return atsUrl + "/ws/v1/timeline/HIVE_QUERY_ID?primaryFilter=operationid:%22" + operationId + "%22";
+  }
+
+  @Override
+  public String tezDagDirectUrl(String entity) {
+    return atsUrl + "/ws/v1/timeline/TEZ_DAG_ID/" + entity;
+  }
+
+  @Override
+  public String tezDagNameUrl(String name) {
+    return atsUrl + "/ws/v1/timeline/TEZ_DAG_ID?primaryFilter=dagName:" + name;
+  }
+
+  @Override
+  public String tezVerticesListForDAGUrl(String dagId) {
+    return atsUrl + "/ws/v1/timeline/TEZ_VERTEX_ID?primaryFilter=TEZ_DAG_ID:" + dagId;
+  }
+
+  @Override
+  public JSONObject hiveQueryIdsForUser(String username) {
+    String hiveQueriesListUrl = atsUrl + "/ws/v1/timeline/HIVE_QUERY_ID?primaryFilter=requestuser:" + username;
+    String response = readFromWithDefault(hiveQueriesListUrl, "{ \"entities\" : [  ] }");
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  @Override
+  public JSONObject hiveQueryIdByOperationId(String operationId) {
+    String hiveQueriesListUrl = hiveQueryIdOperationIdUrl(operationId);
+    String response = readFromWithDefault(hiveQueriesListUrl, EMPTY_ENTITIES_JSON);
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  @Override
+  public JSONObject tezDagByName(String name) {
+    String tezDagUrl = tezDagNameUrl(name);
+    String response = readFromWithDefault(tezDagUrl, EMPTY_ENTITIES_JSON);
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  @Override
+  public JSONObject tezDagByEntity(String entity) {
+    String tezDagEntityUrl = tezDagEntityUrl(entity);
+    String response = readFromWithDefault(tezDagEntityUrl, EMPTY_ENTITIES_JSON);
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  /**
+   * fetches the HIVE_QUERY_ID from ATS for given user between given time period
+   * @param username: username for which to fetch hive query IDs
+   * @param startTime: time in miliseconds, inclusive
+   * @param endTime: time in miliseconds, exclusive
+   * @return
+   */
+  @Override
+  public JSONObject hiveQueryIdsForUserByTime(String username, long startTime, long endTime) {
+    StringBuilder url = new StringBuilder();
+    url.append(atsUrl).append("/ws/v1/timeline/HIVE_QUERY_ID?")
+      .append("windowStart=").append(startTime)
+      .append("&windowEnd=").append(endTime)
+      .append("&primaryFilter=requestuser:").append(username);
+    String hiveQueriesListUrl = url.toString();
+
+    String response = readFromWithDefault(hiveQueriesListUrl, EMPTY_ENTITIES_JSON);
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  @Override
+  public JSONObject hiveQueryEntityByEntityId(String hiveEntityId) {
+    StringBuilder url = new StringBuilder();
+    url.append(atsUrl).append("/ws/v1/timeline/HIVE_QUERY_ID/").append(hiveEntityId);
+    String hiveQueriesListUrl = url.toString();
+    String response = readFromWithDefault(hiveQueriesListUrl, EMPTY_ENTITIES_JSON);
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  private String tezDagEntityUrl(String entity) {
+    return atsUrl + "/ws/v1/timeline/TEZ_DAG_ID?primaryFilter=callerId:" + entity;
+  }
+
+  public boolean checkATSStatus() throws IOException {
+    String url = atsUrl + "/ws/v1/timeline/";
+    InputStream responseInputStream = context.getURLStreamProvider().readAsCurrent(url, "GET",
+            (String)null, new HashMap<String, String>());
+     IOUtils.toString(responseInputStream);
+    return true;
+  }
+
+  @Override
+  public JSONObject tezVerticesListForDAG(String dagId) {
+    String response = readFromWithDefault(tezVerticesListForDAGUrl(dagId), "{ \"entities\" : [  ] }");
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+
+
+  protected String readFromWithDefault(String atsUrl, String defaultResponse) {
+    String response;
+    try {
+      InputStream responseInputStream = context.getURLStreamProvider().readAsCurrent(atsUrl, "GET",
+          (String)null, new HashMap<String, String>());
+      response = IOUtils.toString(responseInputStream);
+    } catch (IOException e) {
+      LOG.error("Error while reading from ATS", e);
+      response = defaultResponse;
+    }
+    return response;
+  }
+
+  public String getAtsUrl() {
+    return atsUrl;
+  }
+
+  public void setAtsUrl(String atsUrl) {
+    this.atsUrl = atsUrl;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/HiveQueryId.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/HiveQueryId.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/HiveQueryId.java
new file mode 100644
index 0000000..cb261d1
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/HiveQueryId.java
@@ -0,0 +1,42 @@
+/**
+ * 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.view.hive20.resources.jobs.atsJobs;
+
+import org.json.simple.JSONObject;
+
+import java.util.List;
+
+public class HiveQueryId {
+  public static long ATS_15_RESPONSE_VERSION = 2; // version returned from ATS 1.5 release
+
+  public String url;
+
+  public String entity;
+  public String query;
+
+  public List<String> dagNames;
+
+  public List<JSONObject> stages;
+
+  public long starttime;
+  public long duration;
+  public String operationId;
+  public String user;
+  public long version;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/IATSParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/IATSParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/IATSParser.java
new file mode 100644
index 0000000..e925bb0
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/IATSParser.java
@@ -0,0 +1,39 @@
+/**
+ * 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.view.hive20.resources.jobs.atsJobs;
+
+import java.util.List;
+
+public interface IATSParser {
+  List<HiveQueryId> getHiveQueryIdsForUser(String username);
+
+  List<TezVertexId> getVerticesForDAGId(String dagId);
+
+  HiveQueryId getHiveQueryIdByOperationId(String guidString);
+
+  TezDagId getTezDAGByName(String name);
+
+  TezDagId getTezDAGByEntity(String entity);
+
+  List<HiveQueryId> getHiveQueryIdsForUserByTime(String username, long startTime, long endTime);
+
+  HiveQueryId getHiveQueryIdByHiveEntityId(String hiveEntityId);
+
+  List<HiveQueryId> getHiveQueryIdByEntityList(List<String> hiveEntityIds);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezDagId.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezDagId.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezDagId.java
new file mode 100644
index 0000000..184436c
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezDagId.java
@@ -0,0 +1,26 @@
+/**
+ * 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.view.hive20.resources.jobs.atsJobs;
+
+public class TezDagId {
+  public static final String STATUS_UNKNOWN = "UNKNOWN";
+  public String applicationId = "";
+  public String entity = "";
+  public String status = STATUS_UNKNOWN;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezVertexId.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezVertexId.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezVertexId.java
new file mode 100644
index 0000000..8acd683
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/atsJobs/TezVertexId.java
@@ -0,0 +1,24 @@
+/**
+ * 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.view.hive20.resources.jobs.atsJobs;
+
+public class TezVertexId {
+  public String entity;
+  public String vertexName;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParser.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParser.java
new file mode 100644
index 0000000..ee96e05
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParser.java
@@ -0,0 +1,129 @@
+/**
+ * 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.view.hive20.resources.jobs.rm;
+
+import org.apache.ambari.view.hive20.resources.jobs.atsJobs.TezVertexId;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Parser of Resource Manager responses
+ */
+public class RMParser {
+  protected final static Logger LOG =
+      LoggerFactory.getLogger(RMParser.class);
+  private RMRequestsDelegate delegate;
+
+  public RMParser(RMRequestsDelegate delegate) {
+    this.delegate = delegate;
+  }
+
+  /**
+   * Progress of DAG
+   * @param appId App Id
+   * @param dagId DAG Id
+   * @return progress of DAG
+   */
+  public Double getDAGProgress(String appId, String dagId) {
+    String dagIdx = parseDagIdIndex(dagId);
+    JSONObject progresses = delegate.dagProgress(appId, dagIdx);
+
+    double dagProgressValue;
+    if (progresses != null) {
+      JSONObject dagProgress = (JSONObject) progresses.get("dagProgress");
+      dagProgressValue = (Double) (dagProgress.get("progress"));
+    } else {
+      LOG.error("Error while retrieving progress of " + appId + ":" + dagId + ". 0 assumed.");
+      dagProgressValue = 0;
+    }
+    return dagProgressValue;
+  }
+
+  /**
+   * Progress of vertices
+   * @param appId App Id
+   * @param dagId DAG Id
+   * @param vertices vertices list
+   * @return list of vertices
+   */
+  public List<VertexProgress> getDAGVerticesProgress(String appId, String dagId, List<TezVertexId> vertices) {
+    String dagIdx = parseDagIdIndex(dagId);
+
+    Map<String, String> vertexIdToEntityMapping = new HashMap<String, String>();
+    StringBuilder builder = new StringBuilder();
+    if (vertices.size() > 0) {
+      for (TezVertexId vertexId : vertices) {
+        String[] parts = vertexId.entity.split("_");
+        String vertexIdx = parts[parts.length - 1];
+        builder.append(vertexIdx).append(",");
+
+        vertexIdToEntityMapping.put(vertexId.entity, vertexId.vertexName);
+      }
+      builder.setLength(builder.length() - 1); // remove last comma
+    }
+
+    String commaSeparatedVertices = builder.toString();
+
+    List<VertexProgress> parsedVertexProgresses = new LinkedList<VertexProgress>();
+    JSONObject vertexProgressesResponse = delegate.verticesProgress(
+        appId, dagIdx, commaSeparatedVertices);
+    if (vertexProgressesResponse == null) {
+      LOG.error("Error while retrieving progress of vertices " +
+          appId + ":" + dagId + ":" + commaSeparatedVertices + ". 0 assumed for all vertices.");
+      for (TezVertexId vertexId : vertices) {
+        VertexProgress vertexProgressInfo = new VertexProgress();
+        vertexProgressInfo.name = vertexId.vertexName;
+        vertexProgressInfo.progress = 0.0;
+        parsedVertexProgresses.add(vertexProgressInfo);
+      }
+      return parsedVertexProgresses;
+    }
+    JSONArray vertexProgresses = (JSONArray) vertexProgressesResponse.get("vertexProgresses");
+
+    for (Object vertex : vertexProgresses) {
+      JSONObject jsonObject = (JSONObject) vertex;
+
+      VertexProgress vertexProgressInfo = new VertexProgress();
+      vertexProgressInfo.id = (String) jsonObject.get("id");
+      vertexProgressInfo.name = vertexIdToEntityMapping.get(vertexProgressInfo.id);
+      vertexProgressInfo.progress = (Double) jsonObject.get("progress");
+
+      parsedVertexProgresses.add(vertexProgressInfo);
+    }
+    return parsedVertexProgresses;
+  }
+
+  public String parseDagIdIndex(String dagId) {
+    String[] dagIdParts = dagId.split("_");
+    return dagIdParts[dagIdParts.length - 1];
+  }
+
+  public static class VertexProgress {
+    public String id;
+    public String name;
+    public Double progress;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParserFactory.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParserFactory.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParserFactory.java
new file mode 100644
index 0000000..64f268a
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMParserFactory.java
@@ -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.view.hive20.resources.jobs.rm;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.utils.ambari.AmbariApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RMParserFactory {
+  protected final static Logger LOG =
+      LoggerFactory.getLogger(RMParserFactory.class);
+
+  private final ViewContext context;
+  private final AmbariApi ambariApi;
+
+  public RMParserFactory(ViewContext context) {
+    this.context = context;
+    this.ambariApi = new AmbariApi(context);
+  }
+
+  public RMParser getRMParser() {
+    String rmUrl = getRMUrl();
+
+    RMRequestsDelegate delegate = new RMRequestsDelegateImpl(context, rmUrl);
+    return new RMParser(delegate);
+  }
+
+  public String getRMUrl() {
+    return ambariApi.getServices().getRMUrl();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegate.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegate.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegate.java
new file mode 100644
index 0000000..e661833
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegate.java
@@ -0,0 +1,31 @@
+/**
+ * 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.view.hive20.resources.jobs.rm;
+
+import org.json.simple.JSONObject;
+
+public interface RMRequestsDelegate {
+  String dagProgressUrl(String appId, String dagIdx);
+
+  String verticesProgressUrl(String appId, String dagIdx, String vertices);
+
+  JSONObject dagProgress(String appId, String dagIdx);
+
+  JSONObject verticesProgress(String appId, String dagIdx, String commaSeparatedVertices);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegateImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegateImpl.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegateImpl.java
new file mode 100644
index 0000000..ed07b55
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/rm/RMRequestsDelegateImpl.java
@@ -0,0 +1,99 @@
+/**
+ * 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.view.hive20.resources.jobs.rm;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.utils.ServiceFormattedException;
+import org.apache.commons.io.IOUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+public class RMRequestsDelegateImpl implements RMRequestsDelegate {
+  protected final static Logger LOG =
+      LoggerFactory.getLogger(RMRequestsDelegateImpl.class);
+  public static final String EMPTY_ENTITIES_JSON = "{ \"entities\" : [  ] }";
+
+  private ViewContext context;
+  private String rmUrl;
+
+  public RMRequestsDelegateImpl(ViewContext context, String rmUrl) {
+    this.context = context;
+    this.rmUrl = rmUrl;
+  }
+
+  @Override
+  public String dagProgressUrl(String appId, String dagIdx) {
+    return rmUrl + String.format("/proxy/%s/ws/v1/tez/dagProgress?dagID=%s", appId, dagIdx);
+  }
+
+  @Override
+  public String verticesProgressUrl(String appId, String dagIdx, String vertices) {
+    return rmUrl + String.format("/proxy/%s/ws/v1/tez/vertexProgresses?dagID=%s&vertexID=%s", appId, dagIdx, vertices);
+  }
+
+  @Override
+  public JSONObject dagProgress(String appId, String dagIdx) {
+    String url = dagProgressUrl(appId, dagIdx);
+    String response;
+    try {
+      InputStream responseInputStream = context.getURLStreamProvider().readFrom(url, "GET",
+          (String)null, new HashMap<String, String>());
+      response = IOUtils.toString(responseInputStream);
+    } catch (IOException e) {
+      throw new ServiceFormattedException(
+          String.format("R010 DAG %s in app %s not found or ResourceManager is unreachable", dagIdx, appId));
+    }
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  @Override
+  public JSONObject verticesProgress(String appId, String dagIdx, String commaSeparatedVertices) {
+    String url = verticesProgressUrl(appId, dagIdx, commaSeparatedVertices);
+    String response;
+    try {
+      InputStream responseInputStream = context.getURLStreamProvider().readFrom(url, "GET",
+          (String)null, new HashMap<String, String>());
+      response = IOUtils.toString(responseInputStream);
+    } catch (IOException e) {
+      throw new ServiceFormattedException(
+          String.format("R020 DAG %s in app %s not found or ResourceManager is unreachable", dagIdx, appId));
+    }
+    return (JSONObject) JSONValue.parse(response);
+  }
+
+  protected String readFromWithDefault(String url, String defaultResponse) {
+    String response;
+    try {
+      InputStream responseInputStream = context.getURLStreamProvider().readFrom(url, "GET",
+          (String)null, new HashMap<String, String>());
+      response = IOUtils.toString(responseInputStream);
+    } catch (IOException e) {
+      LOG.error("Error while reading from RM", e);
+      response = defaultResponse;
+    }
+    return response;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/IJobControllerFactory.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/IJobControllerFactory.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/IJobControllerFactory.java
new file mode 100644
index 0000000..b11f124
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/IJobControllerFactory.java
@@ -0,0 +1,23 @@
+/**
+ * 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.view.hive20.resources.jobs.viewJobs;
+
+public interface IJobControllerFactory {
+  JobController createControllerForJob(Job job);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/Job.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/Job.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/Job.java
new file mode 100644
index 0000000..d64e354
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/Job.java
@@ -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.view.hive20.resources.jobs.viewJobs;
+
+
+import org.apache.ambari.view.hive20.persistence.utils.Indexed;
+import org.apache.ambari.view.hive20.persistence.utils.PersonalResource;
+
+import java.io.Serializable;
+
+/**
+ * Interface for ExecuteJob bean to create Proxy for it
+ */
+public interface Job extends Serializable,Indexed,PersonalResource {
+  String JOB_STATE_UNKNOWN = "UNKNOWN";
+  String JOB_STATE_INITIALIZED = "INITIALIZED";
+  String JOB_STATE_RUNNING = "RUNNING";
+  String JOB_STATE_FINISHED = "SUCCEEDED";
+  String JOB_STATE_CANCELED = "CANCELED";
+  String JOB_STATE_CLOSED = "CLOSED";
+  String JOB_STATE_ERROR = "ERROR";
+  String JOB_STATE_PENDING = "PENDING";
+
+  String getId();
+
+  void setId(String id);
+
+  String getOwner();
+
+  void setOwner(String owner);
+
+  String getTitle();
+
+  void setTitle(String title);
+
+  String getQueryFile();
+
+  void setQueryFile(String queryFile);
+
+  Long getDateSubmitted();
+
+  void setDateSubmitted(Long dateSubmitted);
+
+  Long getDuration();
+
+  void setDuration(Long duration);
+
+  String getStatus();
+
+  void setStatus(String status);
+
+  String getForcedContent();
+
+  void setForcedContent(String forcedContent);
+
+  String getQueryId();
+
+  void setQueryId(String queryId);
+
+  String getStatusDir();
+
+  void setStatusDir(String statusDir);
+
+  String getDataBase();
+
+  void setDataBase(String dataBase);
+
+  String getLogFile();
+
+  void setLogFile(String logFile);
+
+  String getConfFile();
+
+  void setConfFile(String confFile);
+
+  String getApplicationId();
+
+  void setApplicationId(String applicationId);
+
+  String getDagName();
+
+  void setDagName(String dagName);
+
+  String getDagId();
+
+  void setDagId(String dagId);
+
+  String getSessionTag();
+
+  void setSessionTag(String sessionTag);
+
+  String getSqlState();
+
+  void setSqlState(String sqlState);
+
+  String getStatusMessage();
+
+  void setStatusMessage(String message);
+
+  String getReferrer();
+
+  void setReferrer(String referrer);
+
+  String getGlobalSettings();
+
+  void setGlobalSettings(String globalSettings);
+
+  String getGuid();
+
+  void setGuid(String guid);
+
+  String getHiveQueryId();
+
+  void setHiveQueryId(String hiveQueryId);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobController.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobController.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobController.java
new file mode 100644
index 0000000..e8a2fe3
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobController.java
@@ -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.view.hive20.resources.jobs.viewJobs;
+
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+
+public interface JobController {
+
+  void submit() throws Throwable;
+
+  void cancel() throws ItemNotFound;
+
+  Job getJob();
+
+  /**
+   * Use carefully. Returns unproxied bean object
+   * @return unproxied bean object
+   */
+  Job getJobPOJO();
+
+  void afterCreation();
+
+  void update();
+
+  boolean isModified();
+
+  void clearModified();
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerFactory.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerFactory.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerFactory.java
new file mode 100644
index 0000000..cc79843
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerFactory.java
@@ -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.view.hive20.resources.jobs.viewJobs;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.utils.SharedObjectsFactory;
+
+public class JobControllerFactory implements IJobControllerFactory {
+  private SharedObjectsFactory sharedObjectsFactory;
+  private ViewContext context;
+
+  public JobControllerFactory(ViewContext context, SharedObjectsFactory sharedObjectsFactory) {
+    this.sharedObjectsFactory = sharedObjectsFactory;
+    this.context = context;
+  }
+
+  @Override
+  public JobController createControllerForJob(Job job) {
+    return new JobControllerImpl(context, job,
+        sharedObjectsFactory.getSavedQueryResourceManager(),
+        sharedObjectsFactory.getATSParser(),
+        sharedObjectsFactory.getHdfsApi());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerImpl.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerImpl.java
new file mode 100644
index 0000000..1511e5b
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobControllerImpl.java
@@ -0,0 +1,311 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view.hive20.resources.jobs.viewJobs;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.ConnectionFactory;
+import org.apache.ambari.view.hive20.ConnectionSystem;
+import org.apache.ambari.view.hive20.actor.message.HiveJob;
+import org.apache.ambari.view.hive20.actor.message.SQLStatementJob;
+import org.apache.ambari.view.hive20.client.AsyncJobRunner;
+import org.apache.ambari.view.hive20.client.AsyncJobRunnerImpl;
+import org.apache.ambari.view.hive20.client.ConnectionConfig;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.resources.jobs.ModifyNotificationDelegate;
+import org.apache.ambari.view.hive20.resources.jobs.ModifyNotificationInvocationHandler;
+import org.apache.ambari.view.hive20.resources.jobs.atsJobs.IATSParser;
+import org.apache.ambari.view.hive20.resources.savedQueries.SavedQuery;
+import org.apache.ambari.view.hive20.resources.savedQueries.SavedQueryResourceManager;
+import org.apache.ambari.view.hive20.utils.BadRequestFormattedException;
+import org.apache.ambari.view.hive20.utils.FilePaginator;
+import org.apache.ambari.view.hive20.utils.MisconfigurationFormattedException;
+import org.apache.ambari.view.hive20.utils.ServiceFormattedException;
+import org.apache.ambari.view.utils.hdfs.HdfsApi;
+import org.apache.ambari.view.utils.hdfs.HdfsApiException;
+import org.apache.ambari.view.utils.hdfs.HdfsUtil;
+import org.apache.commons.lang3.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.lang.reflect.Proxy;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class JobControllerImpl implements JobController, ModifyNotificationDelegate {
+    private final static Logger LOG =
+            LoggerFactory.getLogger(JobControllerImpl.class);
+
+    private ViewContext context;
+    private HdfsApi hdfsApi;
+    private Job jobUnproxied;
+    private Job job;
+    private boolean modified;
+
+    private SavedQueryResourceManager savedQueryResourceManager;
+    private IATSParser atsParser;
+
+    /**
+     * JobController constructor
+     * Warning: Create JobControllers ONLY using JobControllerFactory!
+     */
+    public JobControllerImpl(ViewContext context, Job job,
+                             SavedQueryResourceManager savedQueryResourceManager,
+                             IATSParser atsParser,
+                             HdfsApi hdfsApi) {
+        this.context = context;
+        setJobPOJO(job);
+        this.savedQueryResourceManager = savedQueryResourceManager;
+        this.atsParser = atsParser;
+        this.hdfsApi = hdfsApi;
+
+    }
+
+    public String getQueryForJob() {
+        FilePaginator paginator = new FilePaginator(job.getQueryFile(), hdfsApi);
+        String query;
+        try {
+            query = paginator.readPage(0);  //warning - reading only 0 page restricts size of query to 1MB
+        } catch (IOException e) {
+            throw new ServiceFormattedException("F030 Error when reading file " + job.getQueryFile(), e);
+        } catch (InterruptedException e) {
+            throw new ServiceFormattedException("F030 Error when reading file " + job.getQueryFile(), e);
+        }
+        return query;
+    }
+
+    private static final String DEFAULT_DB = "default";
+
+    public String getJobDatabase() {
+        if (job.getDataBase() != null) {
+            return job.getDataBase();
+        } else {
+            return DEFAULT_DB;
+        }
+    }
+
+
+    @Override
+    public void submit() throws Throwable {
+        String jobDatabase = getJobDatabase();
+        String query = getQueryForJob();
+        ConnectionSystem system = ConnectionSystem.getInstance();
+        AsyncJobRunner asyncJobRunner = new AsyncJobRunnerImpl(context, system.getOperationController(context), system.getActorSystem());
+        SQLStatementJob asyncJob = new SQLStatementJob(HiveJob.Type.ASYNC, getStatements(jobDatabase, query), context.getUsername(), job.getId(), job.getLogFile());
+        asyncJobRunner.submitJob(getHiveConnectionConfig(), asyncJob, job);
+
+    }
+
+    private String[] getStatements(String jobDatabase, String query) {
+      String[] queries = query.split(";");
+
+
+      String[] strings = {"use " + jobDatabase};
+      return ArrayUtils.addAll(strings, queries);
+    }
+
+
+    @Override
+    public void cancel() throws ItemNotFound {
+      ConnectionSystem system = ConnectionSystem.getInstance();
+      AsyncJobRunner asyncJobRunner = new AsyncJobRunnerImpl(context, system.getOperationController(context), system.getActorSystem());
+      asyncJobRunner.cancelJob(job.getId(), context.getUsername());
+    }
+
+    @Override
+    public void update() {
+        updateJobDuration();
+    }
+
+
+    @Override
+    public Job getJob() {
+        return job;
+    }
+
+    /**
+     * Use carefully. Returns unproxied bean object
+     * @return unproxied bean object
+     */
+    @Override
+    public Job getJobPOJO() {
+        return jobUnproxied;
+    }
+
+    public void setJobPOJO(Job jobPOJO) {
+        Job jobModifyNotificationProxy = (Job) Proxy.newProxyInstance(jobPOJO.getClass().getClassLoader(),
+                new Class[]{Job.class},
+                new ModifyNotificationInvocationHandler(jobPOJO, this));
+        this.job = jobModifyNotificationProxy;
+
+        this.jobUnproxied = jobPOJO;
+    }
+
+
+    @Override
+    public void afterCreation() {
+        setupStatusDirIfNotPresent();
+        setupQueryFileIfNotPresent();
+        setupLogFileIfNotPresent();
+
+        setCreationDate();
+    }
+
+    public void setupLogFileIfNotPresent() {
+        if (job.getLogFile() == null || job.getLogFile().isEmpty()) {
+            setupLogFile();
+        }
+    }
+
+    public void setupQueryFileIfNotPresent() {
+        if (job.getQueryFile() == null || job.getQueryFile().isEmpty()) {
+            setupQueryFile();
+        }
+    }
+
+    public void setupStatusDirIfNotPresent() {
+        if (job.getStatusDir() == null || job.getStatusDir().isEmpty()) {
+            setupStatusDir();
+        }
+    }
+
+    private static final long MillisInSecond = 1000L;
+
+  public void updateJobDuration() {
+    job.setDuration((System.currentTimeMillis() / MillisInSecond) - (job.getDateSubmitted() / MillisInSecond));
+  }
+
+  public void setCreationDate() {
+    job.setDateSubmitted(System.currentTimeMillis());
+  }
+
+  private void setupLogFile() {
+    LOG.debug("Creating log file for job#" + job.getId());
+
+        String logFile = job.getStatusDir() + "/" + "logs";
+        try {
+            HdfsUtil.putStringToFile(hdfsApi, logFile, "");
+        } catch (HdfsApiException e) {
+            throw new ServiceFormattedException(e);
+        }
+
+        job.setLogFile(logFile);
+        LOG.debug("Log file for job#" + job.getId() + ": " + logFile);
+    }
+
+    private void setupStatusDir() {
+        String newDirPrefix = makeStatusDirectoryPrefix();
+        String newDir = null;
+        try {
+            newDir = HdfsUtil.findUnallocatedFileName(hdfsApi, newDirPrefix, "");
+        } catch (HdfsApiException e) {
+            throw new ServiceFormattedException(e);
+        }
+
+        job.setStatusDir(newDir);
+        LOG.debug("Status dir for job#" + job.getId() + ": " + newDir);
+    }
+
+    private String makeStatusDirectoryPrefix() {
+        String userScriptsPath = context.getProperties().get("jobs.dir");
+
+        if (userScriptsPath == null) { // TODO: move check to initialization code
+            String msg = "jobs.dir is not configured!";
+            LOG.error(msg);
+            throw new MisconfigurationFormattedException("jobs.dir");
+        }
+
+        String normalizedName = String.format("hive-job-%s", job.getId());
+        String timestamp = new SimpleDateFormat("yyyy-MM-dd_hh-mm").format(new Date());
+        return String.format(userScriptsPath +
+                "/%s-%s", normalizedName, timestamp);
+    }
+
+    private void setupQueryFile() {
+        String statusDir = job.getStatusDir();
+        assert statusDir != null : "setupStatusDir() should be called first";
+
+        String jobQueryFilePath = statusDir + "/" + "query.hql";
+
+        try {
+
+            if (job.getForcedContent() != null) {
+
+                HdfsUtil.putStringToFile(hdfsApi, jobQueryFilePath, job.getForcedContent());
+                job.setForcedContent("");  // prevent forcedContent to be written to DB
+
+            } else if (job.getQueryId() != null) {
+
+                String savedQueryFile = getRelatedSavedQueryFile();
+                hdfsApi.copy(savedQueryFile, jobQueryFilePath);
+                job.setQueryFile(jobQueryFilePath);
+
+            } else {
+
+                throw new BadRequestFormattedException("queryId or forcedContent should be passed!", null);
+
+            }
+
+        } catch (IOException e) {
+            throw new ServiceFormattedException("F040 Error when creating file " + jobQueryFilePath, e);
+        } catch (InterruptedException e) {
+            throw new ServiceFormattedException("F040 Error when creating file " + jobQueryFilePath, e);
+        } catch (HdfsApiException e) {
+            throw new ServiceFormattedException(e);
+        }
+        job.setQueryFile(jobQueryFilePath);
+
+        LOG.debug("Query file for job#" + job.getId() + ": " + jobQueryFilePath);
+    }
+
+
+    private ConnectionConfig getHiveConnectionConfig() {
+        return ConnectionFactory.create(context);
+    }
+
+    private String getRelatedSavedQueryFile() {
+        SavedQuery savedQuery;
+        try {
+            savedQuery = savedQueryResourceManager.read(job.getQueryId());
+        } catch (ItemNotFound itemNotFound) {
+            throw new BadRequestFormattedException("queryId not found!", itemNotFound);
+        }
+        return savedQuery.getQueryFile();
+    }
+
+    @Override
+    public boolean onModification(Object object) {
+        setModified(true);
+        return true;
+    }
+
+    @Override
+    public boolean isModified() {
+        return modified;
+    }
+
+    public void setModified(boolean modified) {
+        this.modified = modified;
+    }
+
+    @Override
+    public void clearModified() {
+        setModified(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobImpl.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobImpl.java
new file mode 100644
index 0000000..85ffaf2
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobImpl.java
@@ -0,0 +1,335 @@
+/**
+ * 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.view.hive20.resources.jobs.viewJobs;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import java.beans.Transient;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+/**
+ * Bean to represent saved query
+ */
+public class JobImpl implements Job {
+  private String title = null;
+  private String queryFile = null;
+  private String statusDir = null;
+  private Long dateSubmitted = 0L;
+  private Long duration = 0L;
+  private String forcedContent = null;
+  private String dataBase = null;
+  private String queryId = null;
+
+  private String status = JOB_STATE_UNKNOWN;
+  private String statusMessage = null;
+  private String sqlState = null;
+
+  private String applicationId;
+  private String dagId;
+  private String dagName;
+
+  private String sessionTag;
+  private String referrer;
+  private String globalSettings;
+
+  private String id = null;
+  private String owner = null;
+
+  private String logFile;
+  private String confFile;
+
+  private String guid = null;
+
+  private String hiveQueryId;
+
+  public JobImpl() {}
+  public JobImpl(Map<String, Object> stringObjectMap) throws InvocationTargetException, IllegalAccessException {
+    for (Map.Entry<String, Object> entry : stringObjectMap.entrySet())  {
+      try {
+        PropertyUtils.setProperty(this, entry.getKey(), entry.getValue());
+      } catch (NoSuchMethodException e) {
+        //do nothing, skip
+      }
+    }
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof Job)) return false;
+
+    JobImpl job = (JobImpl) o;
+
+    return id != null ? id.equals(job.id) : job.id == null;
+
+  }
+
+  @Override
+  public int hashCode() {
+    return id != null ? id.hashCode() : 0;
+  }
+
+  @Override
+  @Transient
+  public String getHiveQueryId() {
+    return hiveQueryId;
+  }
+
+  @Override
+  @Transient
+  public void setHiveQueryId(String hiveQueryId) {
+    this.hiveQueryId = hiveQueryId;
+  }
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  @Override
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  @Override
+  public String getOwner() {
+    return owner;
+  }
+
+  @Override
+  public void setOwner(String owner) {
+    this.owner = owner;
+  }
+
+  @Override
+  public String getTitle() {
+    return title;
+  }
+
+  @Override
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  @Override
+  public String getQueryFile() {
+    return queryFile;
+  }
+
+  @Override
+  public void setQueryFile(String queryFile) {
+    this.queryFile = queryFile;
+  }
+
+  @Override
+  public Long getDateSubmitted() {
+    return dateSubmitted;
+  }
+
+  @Override
+  public void setDateSubmitted(Long dateSubmitted) {
+    this.dateSubmitted = dateSubmitted;
+  }
+
+  @Override
+  public Long getDuration() {
+    return duration;
+  }
+
+  @Override
+  public void setDuration(Long duration) {
+    this.duration = duration;
+  }
+
+  @Override
+  public String getStatus() {
+    return status;
+  }
+
+  @Override
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  @Override
+  @Transient
+  public String getForcedContent() {
+    return forcedContent;
+  }
+
+  @Override
+  @Transient
+  public void setForcedContent(String forcedContent) {
+    this.forcedContent = forcedContent;
+  }
+
+  @Override
+  public String getQueryId() {
+    return queryId;
+  }
+
+  @Override
+  public void setQueryId(String queryId) {
+    this.queryId = queryId;
+  }
+
+  @Override
+  public String getStatusDir() {
+    return statusDir;
+  }
+
+  @Override
+  public void setStatusDir(String statusDir) {
+    this.statusDir = statusDir;
+  }
+
+  @Override
+  public String getDataBase() {
+    return dataBase;
+  }
+
+  @Override
+  public void setDataBase(String dataBase) {
+    this.dataBase = dataBase;
+  }
+
+  @Override
+  public String getLogFile() {
+    return logFile;
+  }
+
+  @Override
+  public void setLogFile(String logFile) {
+    this.logFile = logFile;
+  }
+
+  @Override
+  public String getConfFile() {
+    return confFile;
+  }
+
+  @Override
+  public void setConfFile(String confFile) {
+    this.confFile = confFile;
+  }
+
+  @Override
+  public String getApplicationId() {
+    return applicationId;
+  }
+
+  @Override
+  public void setApplicationId(String applicationId) {
+    this.applicationId = applicationId;
+  }
+
+  @Override
+  public String getDagName() {
+    return dagName;
+  }
+
+  @Override
+  public void setDagName(String dagName) {
+    this.dagName = dagName;
+  }
+
+  @Override
+  public String getDagId() {
+    return dagId;
+  }
+
+  @Override
+  public void setDagId(String dagId) {
+    this.dagId = dagId;
+  }
+
+  @Override
+  public String getSessionTag() {
+    return sessionTag;
+  }
+
+  @Override
+  public void setSessionTag(String sessionTag) {
+    this.sessionTag = sessionTag;
+  }
+
+  @Override
+  @Transient
+  public String getStatusMessage() {
+    return statusMessage;
+  }
+
+  @Override
+  @Transient
+  public void setStatusMessage(String statusMessage) {
+    this.statusMessage = statusMessage;
+  }
+
+  @Override
+  public String getSqlState() {
+    return sqlState;
+  }
+
+  @Override
+  public void setSqlState(String sqlState) {
+    this.sqlState = sqlState;
+  }
+
+  @Override
+  public String getReferrer() {
+    return referrer;
+  }
+
+  @Override
+  public void setReferrer(String referrer) {
+    this.referrer = referrer;
+  }
+
+  @Override
+  public String getGlobalSettings() {
+    return globalSettings;
+  }
+
+  @Override
+  public void setGlobalSettings(String globalSettings) {
+    this.globalSettings = globalSettings;
+  }
+
+  @Override
+  public String getGuid() {
+    return guid;
+  }
+
+  @Override
+  public void setGuid(String guid) {
+    this.guid = guid;
+  }
+
+  @Override
+  public String toString() {
+    return new StringBuilder("JobImpl{")
+      .append("id='").append(id)
+      .append(", owner='").append(owner)
+      .append(", hiveQueryId='").append(hiveQueryId)
+      .append(", dagId='").append(dagId)
+      .append(", queryId='").append(queryId)
+      .append('}').toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobInfo.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobInfo.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobInfo.java
new file mode 100644
index 0000000..e4ddc72
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobInfo.java
@@ -0,0 +1,78 @@
+/**
+ * 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.view.hive20.resources.jobs.viewJobs;
+
+public class JobInfo {
+  private String jobId;
+  private String hiveId;
+  private String dagId;
+  private String operationId;
+
+  public JobInfo() {
+  }
+
+  public JobInfo(String jobId, String hiveId, String dagId, String operationId) {
+    this.jobId = jobId;
+    this.hiveId = hiveId;
+    this.dagId = dagId;
+    this.operationId = operationId;
+  }
+
+  public String getJobId() {
+    return jobId;
+  }
+
+  public void setJobId(String jobId) {
+    this.jobId = jobId;
+  }
+
+  public String getHiveId() {
+    return hiveId;
+  }
+
+  public void setHiveId(String hiveId) {
+    this.hiveId = hiveId;
+  }
+
+  public String getDagId() {
+    return dagId;
+  }
+
+  public void setDagId(String dagId) {
+    this.dagId = dagId;
+  }
+
+  public String getOperationId() {
+    return operationId;
+  }
+
+  public void setOperationId(String operationId) {
+    this.operationId = operationId;
+  }
+
+  @Override
+  public String toString() {
+    return new StringBuilder().append("JobInfo{" )
+      .append("jobId=").append(jobId)
+      .append(", hiveId=").append(hiveId)
+      .append(", dagId=").append(dagId)
+      .append(", operationId=").append(operationId)
+      .append('}').toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobResourceManager.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobResourceManager.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobResourceManager.java
new file mode 100644
index 0000000..1bfdcaa
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/viewJobs/JobResourceManager.java
@@ -0,0 +1,93 @@
+/**
+ * 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.view.hive20.resources.jobs.viewJobs;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.persistence.utils.FilteringStrategy;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.resources.PersonalCRUDResourceManager;
+import org.apache.ambari.view.hive20.utils.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+/**
+ * Object that provides CRUD operations for job objects
+ */
+public class JobResourceManager extends PersonalCRUDResourceManager<Job> {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(JobResourceManager.class);
+
+  private IJobControllerFactory jobControllerFactory;
+
+  /**
+   * Constructor
+   * @param context View Context instance
+   */
+  public JobResourceManager(SharedObjectsFactory sharedObjectsFactory, ViewContext context) {
+    super(JobImpl.class, sharedObjectsFactory, context);
+    jobControllerFactory = sharedObjectsFactory.getJobControllerFactory();
+  }
+
+  @Override
+  public Job create(Job object) {
+    super.create(object);
+    JobController jobController = jobControllerFactory.createControllerForJob(object);
+
+    try {
+
+      jobController.afterCreation();
+      saveIfModified(jobController);
+
+    } catch (ServiceFormattedException e) {
+      cleanupAfterErrorAndThrowAgain(object, e);
+    }
+
+    return object;
+  }
+
+  public void saveIfModified(JobController jobController) {
+    if (jobController.isModified()) {
+      save(jobController.getJobPOJO());
+      jobController.clearModified();
+    }
+  }
+
+
+  @Override
+  public Job read(Object id) throws ItemNotFound {
+    return super.read(id);
+  }
+
+  @Override
+  public List<Job> readAll(FilteringStrategy filteringStrategy) {
+    return super.readAll(filteringStrategy);
+  }
+
+  @Override
+  public void delete(Object resourceId) throws ItemNotFound {
+    super.delete(resourceId);
+  }
+
+  public JobController readController(Object id) throws ItemNotFound {
+    Job job = read(id);
+    return jobControllerFactory.createControllerForJob(job);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceItem.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceItem.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceItem.java
new file mode 100644
index 0000000..f9478be
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceItem.java
@@ -0,0 +1,78 @@
+/**
+ * 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.view.hive20.resources.resources;
+
+import org.apache.ambari.view.hive20.persistence.utils.PersonalResource;
+import org.apache.commons.beanutils.BeanUtils;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+/**
+ * Bean to represent file resource
+ */
+public class FileResourceItem implements Serializable, PersonalResource {
+  private String name;
+  private String path;
+
+  private String id;
+  private String owner;
+
+  public FileResourceItem() {}
+  public FileResourceItem(Map<String, Object> stringObjectMap) throws InvocationTargetException, IllegalAccessException {
+    BeanUtils.populate(this, stringObjectMap);
+  }
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  @Override
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  @Override
+  public String getOwner() {
+    return owner;
+  }
+
+  @Override
+  public void setOwner(String owner) {
+    this.owner = owner;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getPath() {
+    return path;
+  }
+
+  public void setPath(String path) {
+    this.path = path;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceManager.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceManager.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceManager.java
new file mode 100644
index 0000000..bc52158
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceManager.java
@@ -0,0 +1,65 @@
+/**
+ * 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.view.hive20.resources.resources;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive20.persistence.IStorageFactory;
+import org.apache.ambari.view.hive20.persistence.utils.FilteringStrategy;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.resources.PersonalCRUDResourceManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Object that provides CRUD operations for resource objects
+ */
+public class FileResourceResourceManager extends PersonalCRUDResourceManager<FileResourceItem> {
+  private final static Logger LOG =
+      LoggerFactory.getLogger(FileResourceResourceManager.class);
+
+  /**
+   * Constructor
+   * @param context View Context instance
+   */
+  public FileResourceResourceManager(IStorageFactory storageFactory, ViewContext context) {
+    super(FileResourceItem.class, storageFactory, context);
+  }
+
+  @Override
+  public FileResourceItem create(FileResourceItem object) {
+    return super.create(object);
+  }
+
+  @Override
+  public FileResourceItem read(Object id) throws ItemNotFound {
+    return super.read(id);
+  }
+
+  @Override
+  public void delete(Object resourceId) throws ItemNotFound {
+    super.delete(resourceId);
+  }
+
+  @Override
+  public List<FileResourceItem> readAll(FilteringStrategy filteringStrategy) {
+    return super.readAll(filteringStrategy);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceProvider.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceProvider.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceProvider.java
new file mode 100644
index 0000000..411099f
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceResourceProvider.java
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view.hive20.resources.resources;
+
+import org.apache.ambari.view.*;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.persistence.utils.OnlyOwnersFilteringStrategy;
+import org.apache.ambari.view.hive20.utils.SharedObjectsFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource provider for resource
+ */
+public class FileResourceResourceProvider implements ResourceProvider<FileResourceItem> {
+  @Inject
+  ViewContext context;
+
+  protected FileResourceResourceManager resourceManager = null;
+  protected final static Logger LOG =
+      LoggerFactory.getLogger(FileResourceResourceProvider.class);
+
+  protected synchronized FileResourceResourceManager getResourceManager() {
+    if (resourceManager == null) {
+      resourceManager = new FileResourceResourceManager(new SharedObjectsFactory(context), context);
+    }
+    return resourceManager;
+  }
+
+  @Override
+  public FileResourceItem getResource(String resourceId, Set<String> properties) throws SystemException, NoSuchResourceException, UnsupportedPropertyException {
+    try {
+      return getResourceManager().read(resourceId);
+    } catch (ItemNotFound itemNotFound) {
+      throw new NoSuchResourceException(resourceId);
+    }
+  }
+
+  @Override
+  public Set<FileResourceItem> getResources(ReadRequest readRequest) throws SystemException, NoSuchResourceException, UnsupportedPropertyException {
+    if (context == null) {
+      return new HashSet<FileResourceItem>();
+    }
+    return new HashSet<FileResourceItem>(getResourceManager().readAll(
+        new OnlyOwnersFilteringStrategy(this.context.getUsername())));
+  }
+
+  @Override
+  public void createResource(String s, Map<String, Object> stringObjectMap) throws SystemException, ResourceAlreadyExistsException, NoSuchResourceException, UnsupportedPropertyException {
+    FileResourceItem item = null;
+    try {
+      item = new FileResourceItem(stringObjectMap);
+    } catch (InvocationTargetException e) {
+      throw new SystemException("error on creating resource", e);
+    } catch (IllegalAccessException e) {
+      throw new SystemException("error on creating resource", e);
+    }
+    getResourceManager().create(item);
+  }
+
+  @Override
+  public boolean updateResource(String resourceId, Map<String, Object> stringObjectMap) throws SystemException, NoSuchResourceException, UnsupportedPropertyException {
+    FileResourceItem item = null;
+    try {
+      item = new FileResourceItem(stringObjectMap);
+    } catch (InvocationTargetException e) {
+      throw new SystemException("error on updating resource", e);
+    } catch (IllegalAccessException e) {
+      throw new SystemException("error on updating resource", e);
+    }
+    try {
+      getResourceManager().update(item, resourceId);
+    } catch (ItemNotFound itemNotFound) {
+      throw new NoSuchResourceException(resourceId);
+    }
+    return true;
+  }
+
+  @Override
+  public boolean deleteResource(String resourceId) throws SystemException, NoSuchResourceException, UnsupportedPropertyException {
+    try {
+      getResourceManager().delete(resourceId);
+    } catch (ItemNotFound itemNotFound) {
+      throw new NoSuchResourceException(resourceId);
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceService.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceService.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceService.java
new file mode 100644
index 0000000..3ed8d17
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/resources/FileResourceService.java
@@ -0,0 +1,180 @@
+/**
+ * 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.view.hive20.resources.resources;
+
+import org.apache.ambari.view.ViewResourceHandler;
+import org.apache.ambari.view.hive20.BaseService;
+import org.apache.ambari.view.hive20.persistence.utils.ItemNotFound;
+import org.apache.ambari.view.hive20.persistence.utils.OnlyOwnersFilteringStrategy;
+import org.apache.ambari.view.hive20.utils.NotFoundFormattedException;
+import org.apache.ambari.view.hive20.utils.ServiceFormattedException;
+import org.json.simple.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.List;
+
+/**
+ * Servlet for Resources
+ * API:
+ * GET /:id
+ *      read resource
+ * POST /
+ *      create new resource
+ * GET /
+ *      get all resource of current user
+ */
+public class FileResourceService extends BaseService {
+  @Inject
+  ViewResourceHandler handler;
+
+  protected FileResourceResourceManager resourceManager = null;
+  protected final static Logger LOG =
+      LoggerFactory.getLogger(FileResourceService.class);
+
+  protected synchronized FileResourceResourceManager getResourceManager() {
+    if (resourceManager == null) {
+      resourceManager = new FileResourceResourceManager(getSharedObjectsFactory(), context);
+    }
+    return resourceManager;
+  }
+
+  /**
+   * Get single item
+   */
+  @GET
+  @Path("{id}")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getOne(@PathParam("id") String id) {
+    try {
+      FileResourceItem fileResourceItem = getResourceManager().read(id);
+      JSONObject object = new JSONObject();
+      object.put("fileResource", fileResourceItem);
+      return Response.ok(object).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (ItemNotFound itemNotFound) {
+      throw new NotFoundFormattedException(itemNotFound.getMessage(), itemNotFound);
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Delete single item
+   */
+  @DELETE
+  @Path("{id}")
+  public Response delete(@PathParam("id") String id) {
+    try {
+      getResourceManager().delete(id);
+      return Response.status(204).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (ItemNotFound itemNotFound) {
+      throw new NotFoundFormattedException(itemNotFound.getMessage(), itemNotFound);
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Get all resources
+   */
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getList() {
+    try {
+      LOG.debug("Getting all resources");
+      List items = getResourceManager().readAll(
+          new OnlyOwnersFilteringStrategy(this.context.getUsername()));  //TODO: move strategy to PersonalCRUDRM
+
+      JSONObject object = new JSONObject();
+      object.put("fileResources", items);
+      return Response.ok(object).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Update item
+   */
+  @PUT
+  @Path("{id}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  public Response update(ResourceRequest request,
+                         @PathParam("id") String id) {
+    try {
+      getResourceManager().update(request.fileResource, id);
+      return Response.status(204).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (ItemNotFound itemNotFound) {
+      throw new NotFoundFormattedException(itemNotFound.getMessage(), itemNotFound);
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Create resource
+   */
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  public Response create(ResourceRequest request, @Context HttpServletResponse response,
+                         @Context UriInfo ui) {
+    try {
+      getResourceManager().create(request.fileResource);
+
+      FileResourceItem item = null;
+
+      item = getResourceManager().read(request.fileResource.getId());
+
+      response.setHeader("Location",
+          String.format("%s/%s", ui.getAbsolutePath().toString(), request.fileResource.getId()));
+
+      JSONObject object = new JSONObject();
+      object.put("fileResource", item);
+      return Response.ok(object).status(201).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (ItemNotFound itemNotFound) {
+      throw new NotFoundFormattedException(itemNotFound.getMessage(), itemNotFound);
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Wrapper object for json mapping
+   */
+  public static class ResourceRequest {
+    public FileResourceItem fileResource;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/853a1ce7/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/savedQueries/SavedQuery.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/savedQueries/SavedQuery.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/savedQueries/SavedQuery.java
new file mode 100644
index 0000000..cbb4e4a
--- /dev/null
+++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/savedQueries/SavedQuery.java
@@ -0,0 +1,96 @@
+/**
+ * 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.view.hive20.resources.savedQueries;
+
+import org.apache.ambari.view.hive20.persistence.utils.PersonalResource;
+import org.apache.commons.beanutils.BeanUtils;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+/**
+ * Bean to represent saved query
+ */
+public class SavedQuery implements Serializable, PersonalResource {
+  private String queryFile;
+  private String dataBase;
+  private String title;
+  private String shortQuery;
+
+  private String id;
+  private String owner;
+
+  public SavedQuery() {}
+  public SavedQuery(Map<String, Object> stringObjectMap) throws InvocationTargetException, IllegalAccessException {
+    BeanUtils.populate(this, stringObjectMap);
+  }
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  @Override
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  @Override
+  public String getOwner() {
+    return owner;
+  }
+
+  @Override
+  public void setOwner(String owner) {
+    this.owner = owner;
+  }
+
+  public String getQueryFile() {
+    return queryFile;
+  }
+
+  public void setQueryFile(String queryFile) {
+    this.queryFile = queryFile;
+  }
+
+  public String getDataBase() {
+    return dataBase;
+  }
+
+  public void setDataBase(String dataBase) {
+    this.dataBase = dataBase;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  public String getShortQuery() {
+    return shortQuery;
+  }
+
+  public void setShortQuery(String shortQuery) {
+    this.shortQuery = shortQuery;
+  }
+}