incubator-hcatalog-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ga...@apache.org
Subject svn commit: r1365722 [8/11] - in /incubator/hcatalog/trunk: ./ ant/ conf/ hcatalog-pig-adapter/ ivy/ src/docs/src/documentation/content/xdocs/ src/docs/src/documentation/content/xdocs/images/ src/java/org/apache/hcatalog/mapreduce/ src/test/e2e/templet...
Date Wed, 25 Jul 2012 20:29:49 GMT
Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,856 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+import org.apache.commons.exec.ExecuteException;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+
+
+/**
+ * Run hcat on the local server using the ExecService.  This is
+ * the backend of the ddl web service.
+ */
+public class HcatDelegator extends LauncherDelegator {
+    private static final Log LOG = LogFactory.getLog(HcatDelegator.class);
+    private ExecService execService;
+
+    public HcatDelegator(AppConfig appConf, ExecService execService) {
+        super(appConf);
+        this.execService = execService;
+    }
+
+    /**
+     * Run the local hcat executable.
+     */
+    public ExecBean run(String user, String exec, boolean format,
+                        String group, String permissions)
+        throws NotAuthorizedException, BusyException, ExecuteException, IOException
+    {
+        SecureProxySupport proxy = new SecureProxySupport();
+        try {
+            List<String> args = makeArgs(exec, format, group, permissions);
+            proxy.open(user, appConf);
+
+            // Setup the hadoop vars to specify the user.
+            String cp = makeOverrideClasspath(appConf);
+            Map<String, String> env = TempletonUtils.hadoopUserEnv(user, cp);
+            proxy.addEnv(env);
+            proxy.addArgs(args);
+            return execService.run(appConf.clusterHcat(), args, env);
+        } catch (InterruptedException e) {
+            throw new IOException(e);
+        } finally {
+            if (proxy != null)
+                proxy.close();
+        }
+    }
+
+    private List<String> makeArgs(String exec, boolean format,
+                                  String group, String permissions) {
+        ArrayList<String> args = new ArrayList<String>();
+        args.add("-e");
+        args.add(exec);
+        if (TempletonUtils.isset(group)) {
+            args.add("-g");
+            args.add(group);
+        }
+        if (TempletonUtils.isset(permissions)) {
+            args.add("-p");
+            args.add(permissions);
+        }
+        if (format) {
+            args.add("-D");
+            args.add("hive.ddl.output.format=json");
+            // Use both args to ease development.  Delete this one on
+            // May 1.
+            args.add("-D");
+            args.add("hive.format=json");
+        }
+
+        return args;
+    }
+
+    /**
+     * Return a json description of the database.
+     */
+    public Response descDatabase(String user, String db, boolean extended)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "desc database " + db + "; ";
+        if (extended)
+            exec = "desc database extended " + db + "; ";
+
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(res).build();
+        } catch (HcatException e) {
+            if (e.execBean.stderr.indexOf("Error in semantic analysis") > -1) {
+                return JsonBuilder.create().
+                        put("error", "Database " + db + " does not exist")
+                        .put("errorCode", "404")
+                        .put("database", db).build();
+            }
+            throw new HcatException("unable to describe database: " + db,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json "show databases like".  This will return a list of
+     * databases.
+     */
+    public Response listDatabases(String user, String dbPattern)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("show databases like '%s';", dbPattern);
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(res)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to show databases for: " + dbPattern,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Create a database with the given name
+     */
+    public Response createDatabase(String user, DatabaseDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "create database";
+        if (desc.ifNotExists)
+            exec += " if not exists";
+        exec += " " + desc.database;
+        if (TempletonUtils.isset(desc.comment))
+            exec += String.format(" comment '%s'", desc.comment);
+        if (TempletonUtils.isset(desc.location))
+            exec += String.format(" location '%s'", desc.location);
+        if (TempletonUtils.isset(desc.properties))
+            exec += String.format(" with dbproperties (%s)",
+                                  makePropertiesStatement(desc.properties));
+        exec += ";";
+
+        String res = jsonRun(user, exec, desc.group, desc.permissions);
+        return JsonBuilder.create(res)
+            .put("database", desc.database)
+            .build();
+    }
+
+    /**
+     * Drop the given database
+     */
+    public Response dropDatabase(String user, String db,
+                                 boolean ifExists, String option,
+                                 String group, String permissions)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "drop database";
+        if (ifExists)
+            exec += " if exists";
+        exec += " " + db;
+        if (TempletonUtils.isset(option))
+            exec += " " + option;
+        exec += ";";
+
+        String res = jsonRun(user, exec, group, permissions);
+        return JsonBuilder.create(res)
+            .put("database", db)
+            .build();
+    }
+
+    /**
+     * Create a table.
+     */
+    public Response createTable(String user, String db, TableDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = makeCreateTable(db, desc);
+
+        try {
+            String res = jsonRun(user, exec, desc.group, desc.permissions, true);
+
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", desc.table)
+                .build();
+        } catch (final HcatException e) {
+            throw new HcatException("unable to create table: " + desc.table,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Create a table like another.
+     */
+    public Response createTableLike(String user, String db, TableLikeDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; create", db);
+
+        if (desc.external)
+            exec += " external";
+        exec += String.format(" table %s like %s", desc.newTable, desc.existingTable);
+        if (TempletonUtils.isset(desc.location))
+            exec += String.format(" location '%s'", desc.location);
+        exec += ";";
+
+        try {
+            String res = jsonRun(user, exec, desc.group, desc.permissions, true);
+
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", desc.newTable)
+                .build();
+        } catch (final HcatException e) {
+            throw new HcatException("unable to create table: " + desc.newTable,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json description of the table.
+     */
+    public Response descTable(String user, String db, String table, boolean extended)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "use " + db + "; ";
+        if (extended)
+            exec += "desc extended " + table + "; ";
+        else
+            exec += "desc " + table + "; ";
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to describe table: " + table,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json "show table like".  This will return a list of
+     * tables.
+     */
+    public Response listTables(String user, String db, String tablePattern)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; show tables like '%s';",
+                                    db, tablePattern);
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to show tables for: " + tablePattern,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json "show table extended like".  This will return
+     * only the first single table.
+     */
+    public Response descExtendedTable(String user, String db, String table)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; show table extended like %s;",
+                                    db, table);
+        try {
+            String res = jsonRun(user, exec);
+            JsonBuilder jb = JsonBuilder.create(singleTable(res, table))
+                .remove("tableName")
+                .put("database", db)
+                .put("table", table);
+
+            // If we can get them from HDFS, add group and permission
+            String loc = (String) jb.getMap().get("location");
+            if (loc != null && loc.startsWith("hdfs://")) {
+                try {
+                    FileSystem fs = FileSystem.get(appConf);
+                    FileStatus status = fs.getFileStatus(new Path(new URI(loc)));
+                    jb.put("group", status.getGroup());
+                    jb.put("permission", status.getPermission().toString());
+                } catch (Exception e) {
+                    LOG.warn(e.getMessage() + " Couldn't get permissions for " + loc);
+                }
+            }
+            return jb.build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to show table: " + table, e.execBean, exec);
+        }
+    }
+
+    // Format a list of Columns for a create statement
+    private String makeCols(List<ColumnDesc> cols) {
+        ArrayList<String> res = new ArrayList<String>();
+        for (ColumnDesc col : cols)
+            res.add(makeOneCol(col));
+        return StringUtils.join(res, ", ");
+    }
+
+    // Format a Column for a create statement
+    private String makeOneCol(ColumnDesc col) {
+        String res = String.format("%s %s", col.name, col.type);
+        if (TempletonUtils.isset(col.comment))
+            res += String.format(" comment '%s'", col.comment);
+        return res;
+    }
+
+    // Make a create table statement
+    private String makeCreateTable(String db, TableDesc desc) {
+        String exec = String.format("use %s; create", db);
+
+        if (desc.external)
+            exec += " external";
+        exec += " table";
+        if (desc.ifNotExists)
+            exec += " if not exists";
+        exec += " " + desc.table;
+
+        if (TempletonUtils.isset(desc.columns))
+            exec += String.format("(%s)", makeCols(desc.columns));
+        if (TempletonUtils.isset(desc.comment))
+            exec += String.format(" comment '%s'", desc.comment);
+        if (TempletonUtils.isset(desc.partitionedBy))
+            exec += String.format(" partitioned by (%s)", makeCols(desc.partitionedBy));
+        if (desc.clusteredBy != null)
+            exec += String.format(" clustered by %s", makeClusteredBy(desc.clusteredBy));
+        if (desc.format != null)
+            exec += " " + makeStorageFormat(desc.format);
+        if (TempletonUtils.isset(desc.location))
+            exec += String.format(" location '%s'", desc.location);
+        if (TempletonUtils.isset(desc.tableProperties))
+            exec += String.format(" tblproperties (%s)",
+                                  makePropertiesStatement(desc.tableProperties));
+        exec += ";";
+
+        return exec;
+    }
+
+    // Format a clustered by statement
+    private String makeClusteredBy(TableDesc.ClusteredByDesc desc) {
+        String res = String.format("(%s)", StringUtils.join(desc.columnNames, ", "));
+        if (TempletonUtils.isset(desc.sortedBy))
+            res += String.format(" sorted by (%s)", makeClusterSortList(desc.sortedBy));
+        res += String.format(" into %s buckets", desc.numberOfBuckets);
+
+        return res;
+    }
+
+    // Format a sorted by statement
+    private String makeClusterSortList(List<TableDesc.ClusterSortOrderDesc> descs) {
+        ArrayList<String> res = new ArrayList<String>();
+        for (TableDesc.ClusterSortOrderDesc desc : descs)
+            res.add(makeOneClusterSort(desc));
+        return StringUtils.join(res, ", ");
+    }
+
+    // Format a single cluster sort statement
+    private String makeOneClusterSort(TableDesc.ClusterSortOrderDesc desc) {
+        return String.format("%s %s", desc.columnName, desc.order.toString());
+    }
+
+    // Format the storage format statements
+    private String makeStorageFormat(TableDesc.StorageFormatDesc desc) {
+        String res = "";
+
+        if (desc.rowFormat != null)
+            res += makeRowFormat(desc.rowFormat);
+        if (TempletonUtils.isset(desc.storedAs))
+            res += String.format(" stored as %s", desc.storedAs);
+        if (desc.storedBy != null)
+            res += " " + makeStoredBy(desc.storedBy);
+
+        return res;
+    }
+
+    // Format the row format statement
+    private String makeRowFormat(TableDesc.RowFormatDesc desc) {
+        String res =
+            makeTermBy(desc.fieldsTerminatedBy, "fields")
+            + makeTermBy(desc.collectionItemsTerminatedBy, "collection items")
+            + makeTermBy(desc.mapKeysTerminatedBy, "map keys")
+            + makeTermBy(desc.linesTerminatedBy, "lines");
+
+        if (TempletonUtils.isset(res))
+            return "row format delimited" + res;
+        else if (desc.serde != null)
+            return makeSerdeFormat(desc.serde);
+        else
+            return "";
+    }
+
+    // A row format terminated by clause
+    private String makeTermBy(String sep, String fieldName) {
+
+        if (TempletonUtils.isset(sep))
+          return String.format(" %s terminated by '%s'", fieldName, sep);
+        else
+            return "";
+    }
+
+    // Format the serde statement
+    private String makeSerdeFormat(TableDesc.SerdeDesc desc) {
+        String res = "row format serde " + desc.name;
+        if (TempletonUtils.isset(desc.properties))
+            res += String.format(" with serdeproperties (%s)",
+                                 makePropertiesStatement(desc.properties));
+        return res;
+    }
+
+    // Format the properties statement
+    private String makePropertiesStatement(Map<String, String> properties) {
+        ArrayList<String> res = new ArrayList<String>();
+        for (Map.Entry<String, String> e : properties.entrySet())
+            res.add(String.format("'%s'='%s'", e.getKey(), e.getValue()));
+        return StringUtils.join(res, ", ");
+    }
+
+    // Format the stored by statement
+    private String makeStoredBy(TableDesc.StoredByDesc desc) {
+        String res = String.format("stored by '%s'", desc.className);
+        if (TempletonUtils.isset(desc.properties))
+            res += String.format(" with serdeproperties (%s)",
+                                 makePropertiesStatement(desc.properties));
+        return res;
+    }
+
+    // Pull out the first table from the "show extended" json.
+    private String singleTable(String json, String table)
+        throws IOException
+    {
+        Map obj = JsonBuilder.jsonToMap(json);
+        if (JsonBuilder.isError(obj))
+            return json;
+
+        List tables = (List) obj.get("tables");
+        if (TempletonUtils.isset(tables))
+            return JsonBuilder.mapToJson(tables.get(0));
+        else {
+            return JsonBuilder
+                .createError(String.format("Table %s does not exist", table),
+                             JsonBuilder.MISSING).
+                buildJson();
+        }
+    }
+
+    /**
+     * Drop a table.
+     */
+    public Response dropTable(String user, String db,
+                              String table, boolean ifExists,
+                              String group, String permissions)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; drop table", db);
+        if (ifExists)
+            exec += " if exists";
+        exec += String.format(" %s;", table);
+
+        try {
+            String res = jsonRun(user, exec, group, permissions, true);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to drop table: " + table, e.execBean, exec);
+        }
+    }
+
+    /**
+     * Rename a table.
+     */
+    public Response renameTable(String user, String db,
+                                String oldTable, String newTable,
+                                String group, String permissions)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; alter table %s rename to %s;",
+                                    db, oldTable, newTable);
+        try {
+            String res = jsonRun(user, exec, group, permissions, true);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", newTable)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to rename table: " + oldTable,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Describe one table property.
+     */
+    public Response descTableProperty(String user, String db,
+                                      String table, String property)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        Response res = descTable(user, db, table, true);
+        if (res.getStatus() != JsonBuilder.OK)
+            return res;
+        Map props = tableProperties(res.getEntity());
+        Map found = null;
+        if (props != null) {
+            String value = (String) props.get(property);
+            if (value != null) {
+                found = new HashMap<String, String>();
+                found.put(property, value);
+            }
+        }
+
+        return JsonBuilder.create()
+            .put("database", db)
+            .put("table", table)
+            .put("property", found)
+            .build();
+    }
+
+    /**
+     * List the table properties.
+     */
+    public Response listTableProperties(String user, String db, String table)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        Response res = descTable(user, db, table, true);
+        if (res.getStatus() != JsonBuilder.OK)
+            return res;
+        Map props = tableProperties(res.getEntity());
+        return JsonBuilder.create()
+            .put("database", db)
+            .put("table", table)
+            .put("properties", props)
+            .build();
+    }
+
+    /**
+     * Add one table property.
+     */
+    public Response addOneTableProperty(String user, String db, String table,
+                                        TablePropertyDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec
+            = String.format("use %s; alter table %s set tblproperties ('%s'='%s');",
+                            db, table, desc.name, desc.value);
+        try {
+            String res = jsonRun(user, exec, desc.group, desc.permissions, true);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .put("property", desc.name)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to add table property: " + table,
+                                    e.execBean, exec);
+        }
+    }
+
+    private Map tableProperties(Object extendedTable) {
+        if (! (extendedTable instanceof Map))
+            return null;
+        Map m = (Map) extendedTable;
+        Map tableInfo = (Map) m.get("tableInfo");
+        if (tableInfo == null)
+            return null;
+
+        return (Map) tableInfo.get("parameters");
+    }
+
+    /**
+     * Return a json description of the partitions.
+     */
+    public Response listPartitions(String user, String db, String table)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "use " + db + "; ";
+        exec += "show partitions " + table + "; ";
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to show partitions for table: " + table,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json description of one partition.
+     */
+    public Response descOnePartition(String user, String db, String table,
+                                     String partition)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = "use " + db + "; ";
+        exec += "show table extended like " + table
+            + " partition (" + partition + "); ";
+        try {
+            String res = jsonRun(user, exec);
+            return JsonBuilder.create(singleTable(res, table))
+                .remove("tableName")
+                .put("database", db)
+                .put("table", table)
+                .put("partition", partition)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to show partition: "
+                                    + table + " " + partition,
+                                    e.execBean,
+                                    exec);
+        }
+    }
+
+    /**
+     * Add one partition.
+     */
+    public Response addOnePartition(String user, String db, String table,
+                                    PartitionDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; alter table %s add", db, table);
+        if (desc.ifNotExists)
+            exec += " if not exists";
+        exec += String.format(" partition (%s)", desc.partition);
+        if (TempletonUtils.isset(desc.location))
+            exec += String.format(" location '%s'", desc.location);
+        exec += ";";
+        try {
+            String res = jsonRun(user, exec, desc.group, desc.permissions, true);
+            if (res.indexOf("AlreadyExistsException") > -1) {
+                return JsonBuilder.create().
+                        put("error", "Partition already exists")
+                        .put("errorCode", "409")
+                        .put("database", db)
+                        .put("table", table)
+                        .put("partition", desc.partition).build();
+            }
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .put("partition", desc.partition)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to add partition: " + desc,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Drop a partition.
+     */
+    public Response dropPartition(String user, String db,
+                                  String table, String partition, boolean ifExists,
+                                  String group, String permissions)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; alter table %s drop", db, table);
+        if (ifExists)
+            exec += " if exists";
+        exec += String.format(" partition (%s);", partition);
+
+        try {
+            String res = jsonRun(user, exec, group, permissions, true);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .put("partition", partition)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to drop partition: " + partition,
+                                    e.execBean, exec);
+        }
+    }
+
+    /**
+     * Return a json description of the columns.  Same as
+     * describeTable.
+     */
+    public Response listColumns(String user, String db, String table)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        try {
+            return descTable(user, db, table, false);
+        } catch (HcatException e) {
+            throw new HcatException("unable to show columns for table: " + table,
+                                    e.execBean, e.statement);
+        }
+    }
+
+    /**
+     * Return a json description of one column.
+     */
+    public Response descOneColumn(String user, String db, String table, String column)
+        throws SimpleWebException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        Response res = listColumns(user, db, table);
+        if (res.getStatus() != JsonBuilder.OK)
+            return res;
+
+        Object o = res.getEntity();
+        final Map fields = (o != null && (o instanceof Map)) ? (Map) o : null;
+        if (fields == null)
+            throw new SimpleWebException(500, "Internal error, unable to find column "
+                                         + column);
+
+
+        List<Map> cols = (List) fields.get("columns");
+        Map found = null;
+        if (cols != null) {
+            for (Map col : cols) {
+                if (column.equals(col.get("name"))) {
+                    found = col;
+                    break;
+                }
+            }
+        }
+        if (found == null)
+            throw new SimpleWebException(500, "unable to find column " + column,
+                                         new HashMap<String, Object>() {{
+                                                 put("description", fields);
+                                             }});
+        fields.remove("columns");
+        fields.put("column", found);
+        return Response.fromResponse(res).entity(fields).build();
+    }
+
+    /**
+     * Add one column.
+     */
+    public Response addOneColumn(String user, String db, String table,
+                                 ColumnDesc desc)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        String exec = String.format("use %s; alter table %s add columns (%s %s",
+                                    db, table, desc.name, desc.type);
+        if (TempletonUtils.isset(desc.comment))
+            exec += String.format(" comment '%s'", desc.comment);
+        exec += ");";
+        try {
+            String res = jsonRun(user, exec, desc.group, desc.permissions, true);
+            return JsonBuilder.create(res)
+                .put("database", db)
+                .put("table", table)
+                .put("column", desc.name)
+                .build();
+        } catch (HcatException e) {
+            throw new HcatException("unable to add column: " + desc,
+                                    e.execBean, exec);
+        }
+    }
+
+    // Check that the hcat result is valid and or has a valid json
+    // error
+    private boolean isValid(ExecBean eb, boolean requireEmptyOutput) {
+        if (eb == null)
+            return false;
+
+        try {
+            Map m = JsonBuilder.jsonToMap(eb.stdout);
+            if (m.containsKey("error")) // This is a valid error message.
+                return true;
+        } catch (IOException e) {
+            return false;
+        }
+
+        if (eb.exitcode != 0)
+            return false;
+
+        if (requireEmptyOutput)
+            if (TempletonUtils.isset(eb.stdout))
+                return false;
+
+        return true;
+    }
+
+    // Run an hcat expression and return just the json outout.
+    private String jsonRun(String user, String exec,
+                           String group, String permissions,
+                           boolean requireEmptyOutput)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        ExecBean res = run(user, exec, true, group, permissions);
+
+        if (! isValid(res, requireEmptyOutput))
+            throw new HcatException("Failure calling hcat: " + exec, res, exec);
+
+        return res.stdout;
+    }
+
+    // Run an hcat expression and return just the json outout.  No
+    // permissions set.
+    private String jsonRun(String user, String exec)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        return jsonRun(user, exec, null, null);
+    }
+
+    // Run an hcat expression and return just the json outout.
+    private String jsonRun(String user, String exec,
+                           String group, String permissions)
+        throws HcatException, NotAuthorizedException, BusyException,
+        ExecuteException, IOException
+    {
+        return jsonRun(user, exec, group, permissions, false);
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatException.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatException.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatException.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HcatException.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hcatalog.templeton;
+
+import java.util.HashMap;
+
+/**
+ * Unable to run hcat on the job.
+ */
+public class HcatException extends SimpleWebException {
+    public ExecBean execBean;
+    public String statement;
+
+    public HcatException(String msg, final ExecBean bean, final String statement) {
+        super(500, msg, new HashMap<String, Object>() {{
+                    put("exec", bean);
+                    put("statement", statement);
+                }});
+        execBean = bean;
+        this.statement = statement;
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HiveDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HiveDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HiveDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/HiveDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,107 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.exec.ExecuteException;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+
+/**
+ * Submit a Hive job.
+ *
+ * This is the backend of the hive web service.
+ */
+public class HiveDelegator extends LauncherDelegator {
+
+    public HiveDelegator(AppConfig appConf) {
+        super(appConf);
+    }
+
+    public EnqueueBean run(String user,
+                           String execute, String srcFile, List<String> defines,
+                           String statusdir, String callback, String completedUrl)
+        throws NotAuthorizedException, BadParam, BusyException, QueueException,
+        ExecuteException, IOException, InterruptedException
+    {
+        runAs = user;
+        List<String> args = makeArgs(execute, srcFile, defines, statusdir,
+                                     completedUrl);
+
+        return enqueueController(user, callback, args);
+    }
+
+    private List<String> makeArgs(String execute, String srcFile,
+            List<String> defines, String statusdir, String completedUrl)
+        throws BadParam, IOException, InterruptedException
+    {
+        ArrayList<String> args = new ArrayList<String>();
+        try {
+            args.addAll(makeBasicArgs(execute, srcFile, statusdir, completedUrl));
+            args.add("--");
+            args.add(appConf.hivePath());
+            args.add("--service");
+            args.add("cli");
+            for (String prop : appConf.getStrings(AppConfig.HIVE_PROPS_NAME)) {
+                args.add("--hiveconf");
+                args.add(prop);
+            }
+            for (String prop : defines) {
+                args.add("--hiveconf");
+                args.add(prop);
+            }
+            if (TempletonUtils.isset(execute)) {
+                args.add("-e");
+                args.add(execute);
+            } else if (TempletonUtils.isset(srcFile)) {
+                args.add("-f");
+                args.add(TempletonUtils.hadoopFsPath(srcFile, appConf, runAs)
+                        .getName());
+            }
+        } catch (FileNotFoundException e) {
+            throw new BadParam(e.getMessage());
+        } catch (URISyntaxException e) {
+            throw new BadParam(e.getMessage());
+        }
+
+        return args;
+    }
+
+    private List<String> makeBasicArgs(String execute, String srcFile,
+                                       String statusdir, String completedUrl)
+        throws URISyntaxException, FileNotFoundException, IOException,
+        InterruptedException
+    {
+        ArrayList<String> args = new ArrayList<String>();
+
+        ArrayList<String> allFiles = new ArrayList<String>();
+        if (TempletonUtils.isset(srcFile))
+            allFiles.add(TempletonUtils.hadoopFsFilename(srcFile, appConf,
+                    runAs));
+
+        args.addAll(makeLauncherArgs(appConf, statusdir, completedUrl, allFiles));
+
+        args.add("-archives");
+        args.add(appConf.hiveArchive());
+
+        return args;
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JarDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JarDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JarDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JarDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,95 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.exec.ExecuteException;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+
+/**
+ * Submit a job to the MapReduce queue.
+ *
+ * This is the backend of the mapreduce/jar web service.
+ */
+public class JarDelegator extends LauncherDelegator {
+    public JarDelegator(AppConfig appConf) {
+        super(appConf);
+    }
+
+    public EnqueueBean run(String user, String jar, String mainClass,
+                           String libjars, String files,
+                           List<String> jarArgs, List<String> defines,
+                           String statusdir, String callback, String completedUrl)
+        throws NotAuthorizedException, BadParam, BusyException, QueueException,
+        ExecuteException, IOException, InterruptedException
+    {
+        runAs = user;
+        List<String> args = makeArgs(jar, mainClass,
+                                     libjars, files, jarArgs, defines,
+                                     statusdir, completedUrl);
+
+        return enqueueController(user, callback, args);
+    }
+
+    private List<String> makeArgs(String jar, String mainClass,
+                                  String libjars, String files,
+                                  List<String> jarArgs, List<String> defines,
+                                  String statusdir, String completedUrl)
+        throws BadParam, IOException, InterruptedException
+    {
+        ArrayList<String> args = new ArrayList<String>();
+        try {
+            ArrayList<String> allFiles = new ArrayList();
+            allFiles.add(TempletonUtils.hadoopFsFilename(jar, appConf, runAs));
+
+            args.addAll(makeLauncherArgs(appConf, statusdir,
+                                         completedUrl, allFiles));
+            args.add("--");
+            args.add(appConf.clusterHadoop());
+            args.add("jar");
+            args.add(TempletonUtils.hadoopFsPath(jar, appConf, runAs).getName());
+            if (TempletonUtils.isset(mainClass))
+                args.add(mainClass);
+            if (TempletonUtils.isset(libjars)) {
+                args.add("-libjars");
+                args.add(TempletonUtils.hadoopFsListAsString(libjars, appConf,
+                        runAs));
+            }
+            if (TempletonUtils.isset(files)) {
+                args.add("-files");
+                args.add(TempletonUtils.hadoopFsListAsString(files, appConf,
+                        runAs));
+            }
+
+            for (String d : defines)
+                args.add("-D" + d);
+
+            args.addAll(jarArgs);
+        } catch (FileNotFoundException e) {
+            throw new BadParam(e.getMessage());
+        } catch (URISyntaxException e) {
+            throw new BadParam(e.getMessage());
+        }
+
+        return args;
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JsonBuilder.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JsonBuilder.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JsonBuilder.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/JsonBuilder.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,186 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+import org.codehaus.jackson.map.ObjectMapper;
+
+/**
+ * Helper class to build new json objects with new top level
+ * properties.  Only add non-null entries.
+ */
+public class JsonBuilder {
+    static final int OK = 200;
+    static final int MISSING = 404;
+    static final int SERVER_ERROR = 500;
+
+    // The map we're building.
+    private Map map;
+
+    // Parse the json map.
+    private JsonBuilder(String json)
+        throws IOException
+    {
+        map = jsonToMap(json);
+    }
+
+    /**
+     * Create a new map object from the existing json.
+     */
+    public static JsonBuilder create(String json)
+        throws IOException
+    {
+        return new JsonBuilder(json);
+    }
+
+    /**
+     * Create a new map object.
+     */
+    public static JsonBuilder create()
+        throws IOException
+    {
+        return new JsonBuilder(null);
+    }
+
+    /**
+     * Create a new map error object.
+     */
+    public static JsonBuilder createError(String msg, int code)
+        throws IOException
+    {
+        return new JsonBuilder(null)
+            .put("error", msg)
+            .put("errorCode", code);
+    }
+
+    /**
+     * Add a non-null value to the map.
+     */
+    public JsonBuilder put(String name, Object val) {
+        if (val != null)
+            map.put(name, val);
+        return this;
+    }
+
+    /**
+     * Remove a value from the map.
+     */
+    public JsonBuilder remove(String name) {
+        map.remove(name);
+        return this;
+    }
+
+    /**
+     * Get the underlying map.
+     */
+    public Map getMap() {
+        return map;
+    }
+
+    /**
+     * Turn the map back to response object.
+     */
+    public Response build() {
+        return buildResponse();
+    }
+
+    /**
+     * Turn the map back to json.
+     */
+    public String buildJson()
+        throws IOException
+    {
+        return mapToJson(map);
+    }
+
+    /**
+     * Turn the map back to response object.
+     */
+    public Response buildResponse() {
+        int status = OK;        // Server ok.
+        if (map.containsKey("error"))
+            status = SERVER_ERROR; // Generic http server error.
+        Object o = map.get("errorCode");
+        if (o != null) {
+            try {
+                status = Integer.parseInt(o.toString());
+            } catch (Exception e) {
+                if (o instanceof Number)
+                    status = ((Number) o).intValue();
+            }
+        }
+        return buildResponse(status);
+    }
+
+    /**
+     * Turn the map back to response object.
+     */
+    public Response buildResponse(int status) {
+        return Response.status(status)
+            .entity(map)
+            .type(MediaType.APPLICATION_JSON)
+            .build();
+    }
+
+    /**
+     * Is the object non-empty?
+     */
+    public boolean isset() {
+        return TempletonUtils.isset(map);
+    }
+
+    /**
+     * Check if this is an error doc.
+     */
+    public static boolean isError(Map obj)
+    {
+        return (obj != null) && obj.containsKey("error");
+    }
+
+    /**
+     * Convert a json string to a Map.
+     */
+    public static Map jsonToMap(String json)
+        throws IOException
+    {
+        if (! TempletonUtils.isset(json))
+            return new HashMap<String, Object>();
+        else {
+            ObjectMapper mapper = new ObjectMapper();
+            return mapper.readValue(json, Map.class);
+        }
+    }
+
+    /**
+     * Convert a map to a json string.
+     */
+    public static String mapToJson(Object obj)
+        throws IOException
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        mapper.writeValue(out, obj);
+        return out.toString();
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/LauncherDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/LauncherDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/LauncherDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/LauncherDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,198 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.exec.ExecuteException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.StringUtils;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.hcatalog.templeton.tool.JobState;
+import org.apache.hcatalog.templeton.tool.TempletonControllerJob;
+import org.apache.hcatalog.templeton.tool.TempletonStorage;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+import org.apache.hcatalog.templeton.tool.ZooKeeperStorage;
+
+/**
+ * The helper class for all the Templeton delegator classes that
+ * launch child jobs.
+ */
+public class LauncherDelegator extends TempletonDelegator {
+    private static final Log LOG = LogFactory.getLog(Server.class);
+    public static final String JAR_CLASS = TempletonControllerJob.class.getName();
+    protected String runAs = null;
+
+    public LauncherDelegator(AppConfig appConf) {
+        super(appConf);
+    }
+
+    public void registerJob(String id, String user, String callback)
+        throws IOException
+    {
+        JobState state = null;
+        try {
+            state = new JobState(id, Main.getAppConfigInstance());
+            state.setUser(user);
+            state.setCallback(callback);
+        } finally {
+            if (state != null)
+                state.close();
+        }
+    }
+
+    /**
+     * Enqueue the TempletonControllerJob directly calling doAs.
+     */
+    public EnqueueBean enqueueController(String user, String callback,
+                                                 List<String> args)
+        throws NotAuthorizedException, BusyException, ExecuteException,
+        IOException, QueueException
+    {
+        try {
+            UserGroupInformation ugi = UgiFactory.getUgi(user); 
+
+            final long startTime = System.nanoTime();
+
+            String id = queueAsUser(ugi, args);
+
+            long elapsed = ((System.nanoTime() - startTime) / ((int) 1e6));
+            LOG.debug("queued job " + id + " in " + elapsed + " ms");
+
+            if (id == null)
+                throw new QueueException("Unable to get job id");
+
+            registerJob(id, user, callback);
+
+            return new EnqueueBean(id);
+        } catch (InterruptedException e) {
+            throw new QueueException("Unable to launch job " + e);
+        }
+    }
+
+    private String queueAsUser(UserGroupInformation ugi, final List<String> args)
+        throws IOException, InterruptedException
+    {
+        String id = ugi.doAs(new PrivilegedExceptionAction<String>() {
+                public String run() throws Exception {
+                    String[] array = new String[args.size()];
+                    TempletonControllerJob ctrl = new TempletonControllerJob();
+                    ToolRunner.run(ctrl, args.toArray(array));
+                    return ctrl.getSubmittedId();
+                }
+            });
+
+        return id;
+    }
+
+    public List<String> makeLauncherArgs(AppConfig appConf, String statusdir,
+                                         String completedUrl,
+                                         List<String> copyFiles)
+    {
+        ArrayList<String> args = new ArrayList<String>();
+
+        args.add("-libjars");
+        args.add(appConf.libJars());
+        addCacheFiles(args, appConf);
+
+        // Hadoop vars
+        addDef(args, "user.name", runAs);
+        addDef(args, AppConfig.HADOOP_SPECULATIVE_NAME, "false");
+
+        // Internal vars
+        addDef(args, TempletonControllerJob.STATUSDIR_NAME, statusdir);
+        addDef(args, TempletonControllerJob.COPY_NAME,
+               TempletonUtils.encodeArray(copyFiles));
+        addDef(args, TempletonControllerJob.OVERRIDE_CLASSPATH,
+               makeOverrideClasspath(appConf));
+
+        // Job vars
+        addStorageVars(args);
+        addCompletionVars(args, completedUrl);
+
+        return args;
+    }
+
+    // Storage vars
+    private void addStorageVars(List<String> args) {
+        addDef(args, TempletonStorage.STORAGE_CLASS,
+               appConf.get(TempletonStorage.STORAGE_CLASS));
+        addDef(args, TempletonStorage.STORAGE_ROOT,
+                appConf.get(TempletonStorage.STORAGE_ROOT));
+        addDef(args, ZooKeeperStorage.ZK_HOSTS,
+                appConf.get(ZooKeeperStorage.ZK_HOSTS));
+        addDef(args, ZooKeeperStorage.ZK_SESSION_TIMEOUT,
+                appConf.get(ZooKeeperStorage.ZK_SESSION_TIMEOUT));
+    }
+
+    // Completion notifier vars
+    private void addCompletionVars(List<String> args, String completedUrl) {
+        addDef(args, AppConfig.HADOOP_END_RETRY_NAME,
+               appConf.get(AppConfig.CALLBACK_RETRY_NAME));
+        addDef(args, AppConfig.HADOOP_END_INTERVAL_NAME,
+               appConf.get(AppConfig.CALLBACK_INTERVAL_NAME));
+        addDef(args, AppConfig.HADOOP_END_URL_NAME, completedUrl);
+    }
+
+    /**
+     * Add files to the Distributed Cache for the controller job.
+     */
+    public static void addCacheFiles(List<String> args, AppConfig appConf) {
+        String overrides = appConf.overrideJarsString();
+        if (overrides != null) {
+            args.add("-files");
+            args.add(overrides);
+        }
+    }
+
+    /**
+     * Create the override classpath, which will be added to
+     * HADOOP_CLASSPATH at runtime by the controller job.
+     */
+    public static String makeOverrideClasspath(AppConfig appConf) {
+        String[] overrides = appConf.overrideJars();
+        if (overrides == null)
+            return null;
+
+        ArrayList<String> cp = new ArrayList<String>();
+        for (String fname : overrides) {
+            Path p = new Path(fname);
+            cp.add(p.getName());
+        }
+        return StringUtils.join(":", cp);
+    }
+
+
+    /**
+     * Add a Hadoop command line definition to args if the value is
+     * not null.
+     */
+    public static void addDef(List<String> args, String name, String val) {
+        if (val != null) {
+            args.add("-D");
+            args.add(name + "=" + val);
+        }
+    }
+
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/ListDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/ListDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/ListDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/ListDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,79 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import org.apache.hadoop.mapred.JobID;
+import org.apache.hadoop.mapred.JobProfile;
+import org.apache.hadoop.mapred.JobStatus;
+import org.apache.hadoop.mapred.JobTracker;
+import org.apache.hadoop.mapred.TempletonJobTracker;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hcatalog.templeton.tool.JobState;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+import org.apache.zookeeper.ZooKeeper;
+
+/**
+ * List jobs owned by a user.
+ */
+public class ListDelegator extends TempletonDelegator {
+    public ListDelegator(AppConfig appConf) {
+        super(appConf);
+    }
+
+    public List<String> run(String user)
+        throws NotAuthorizedException, BadParam, IOException
+    {
+        UserGroupInformation ugi = UserGroupInformation.createRemoteUser(user);
+        TempletonJobTracker tracker = null;
+        try {
+            tracker = new TempletonJobTracker(ugi,
+                                              JobTracker.getAddress(appConf),
+                                              appConf);
+
+            ArrayList<String> ids = new ArrayList<String>();
+
+            JobStatus[] jobs = tracker.getAllJobs();
+
+            if (jobs != null) {
+                for (JobStatus job : jobs) {
+                    JobState state = null;
+                    try {
+                        String id = job.getJobID().toString();
+                        state = new JobState(id, Main.getAppConfigInstance());
+                        if (user.equals(state.getUser()))
+                            ids.add(id);
+                    } finally {
+                        if (state != null) {
+                            state.close();
+                        }
+                    }
+                }
+            }
+
+            return ids;
+        } catch (IllegalStateException e) {
+            throw new BadParam(e.getMessage());
+        } finally {
+            if (tracker != null)
+                tracker.close();
+        }
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/Main.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/Main.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/Main.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/Main.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,217 @@
+/*
+ * 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.hcatalog.templeton;
+
+import com.sun.jersey.api.core.PackagesResourceConfig;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hdfs.web.AuthFilter;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.GenericOptionsParser;
+import org.eclipse.jetty.rewrite.handler.RedirectPatternRule;
+import org.eclipse.jetty.rewrite.handler.RewriteHandler;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+/**
+ * The main executable that starts up and runs the Server.
+ */
+public class Main {
+    public static final String SERVLET_PATH = "templeton";
+    private static final Log LOG = LogFactory.getLog(Main.class);
+
+    public static final int DEFAULT_PORT = 8080;
+
+    private static volatile AppConfig conf;
+
+    /**
+     * Retrieve the config singleton.
+     */
+    public static synchronized AppConfig getAppConfigInstance() {
+        if (conf == null)
+            LOG.error("Bug: configuration not yet loaded");
+        return conf;
+    }
+
+    public Main(String[] args) {
+        init(args);
+    }
+
+    public void init(String[] args) {
+        initLogger();
+        conf = loadConfig(args);
+        conf.startCleanup();
+        LOG.debug("Loaded conf " + conf);
+    }
+
+    // Jersey uses java.util.logging - bridge to slf4
+    private void initLogger() {
+        java.util.logging.Logger rootLogger
+            = java.util.logging.LogManager.getLogManager().getLogger("");
+        for (java.util.logging.Handler h : rootLogger.getHandlers())
+            rootLogger.removeHandler(h);
+
+        SLF4JBridgeHandler.install();
+    }
+
+    public AppConfig loadConfig(String[] args) {
+        AppConfig cf = new AppConfig();
+        try {
+            GenericOptionsParser parser = new GenericOptionsParser(cf, args);
+            if (parser.getRemainingArgs().length > 0)
+                usage();
+        } catch (IOException e) {
+            LOG.error("Unable to parse options: " + e);
+            usage();
+        }
+
+        return cf;
+    }
+
+    public void usage() {
+        System.err.println("usage: templeton [-Dtempleton.port=N] [-D...]");
+        System.exit(1);
+    }
+
+    public void run() {
+        int port = conf.getInt(AppConfig.PORT, DEFAULT_PORT);
+        try {
+            checkEnv();
+            runServer(port);
+            System.out.println("templeton: listening on port " + port);
+            LOG.info("Templeton listening on port " + port);
+        } catch (Exception e) {
+            System.err.println("templeton: Server failed to start: " + e.getMessage());
+            LOG.fatal("Server failed to start: " + e);
+            System.exit(1);
+        }
+    }
+
+    private void checkEnv() {
+        checkCurrentDirPermissions();
+        
+    }
+
+    private void checkCurrentDirPermissions() {
+        //org.apache.commons.exec.DefaultExecutor requires
+        // that current directory exists
+        File pwd = new File(".");
+        if(!pwd.exists()){
+            String msg = "Server failed to start: templeton: Current working directory '.' does not exist!";
+            System.err.println(msg);
+            LOG.fatal( msg);
+            System.exit(1);
+        }
+    }
+
+    public Server runServer(int port)
+        throws Exception
+    {
+
+        //Authenticate using keytab
+        if(UserGroupInformation.isSecurityEnabled()){
+            UserGroupInformation.loginUserFromKeytab(conf.kerberosPrincipal(),
+                    conf.kerberosKeytab());
+        }
+        
+        // Create the Jetty server
+        Server server = new Server(port);
+        ServletContextHandler root = new ServletContextHandler(server, "/");
+
+        // Add the Auth filter
+        root.addFilter(makeAuthFilter(), "/*", FilterMapping.REQUEST);
+
+        // Connect Jersey
+        ServletHolder h = new ServletHolder(new ServletContainer(makeJerseyConfig()));
+        root.addServlet(h, "/" + SERVLET_PATH + "/*");
+
+        // Add any redirects
+        addRedirects(server);
+
+        // Start the server
+        server.start();
+        return server;
+    }
+
+    // Configure the AuthFilter with the Kerberos params iff security
+    // is enabled.
+    public FilterHolder makeAuthFilter() {
+        FilterHolder authFilter = new FilterHolder(AuthFilter.class);
+        if (UserGroupInformation.isSecurityEnabled()) {
+            authFilter.setInitParameter("dfs.web.authentication.signature.secret",
+                                        conf.kerberosSecret());
+            authFilter.setInitParameter("dfs.web.authentication.kerberos.principal",
+                                        conf.kerberosPrincipal());
+            authFilter.setInitParameter("dfs.web.authentication.kerberos.keytab",
+                                        conf.kerberosKeytab());
+        }
+        return authFilter;
+    }
+
+    public PackagesResourceConfig makeJerseyConfig() {
+        PackagesResourceConfig rc
+            = new PackagesResourceConfig("org.apache.hcatalog.templeton");
+        HashMap<String, Object> props = new HashMap<String, Object>();
+        props.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
+        props.put("com.sun.jersey.config.property.WadlGeneratorConfig",
+                  "org.apache.hcatalog.templeton.WadlConfig");
+        rc.setPropertiesAndFeatures(props);
+
+        return rc;
+    }
+
+    public void addRedirects(Server server) {
+        RewriteHandler rewrite = new RewriteHandler();
+
+        RedirectPatternRule redirect = new RedirectPatternRule();
+        redirect.setPattern("/templeton/v1/application.wadl");
+        redirect.setLocation("/templeton/application.wadl");
+        rewrite.addRule(redirect);
+
+        HandlerList handlerlist = new HandlerList();
+        ArrayList<Handler> handlers = new ArrayList<Handler>();
+
+        // Any redirect handlers need to be added first
+        handlers.add(rewrite);
+
+        // Now add all the default handlers
+        for (Handler handler : server.getHandlers()) {
+            handlers.add(handler);
+        }
+        Handler[] newlist = new Handler[handlers.size()];
+        handlerlist.setHandlers(handlers.toArray(newlist));
+        server.setHandler(handlerlist);
+    }
+
+    public static void main(String[] args) {
+        Main templeton = new Main(args);
+        templeton.run();
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/MaxByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/MaxByteArrayOutputStream.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/MaxByteArrayOutputStream.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/MaxByteArrayOutputStream.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * An output stream that will only accept the first N bytes of data.
+ */
+public class MaxByteArrayOutputStream extends ByteArrayOutputStream {
+    /**
+     * The max number of bytes stored.
+     */
+    private int maxBytes;
+
+    /**
+     * The number of bytes currently stored.
+     */
+    private int nBytes;
+
+    /**
+     * Create.
+     */
+    public MaxByteArrayOutputStream(int maxBytes) {
+        this.maxBytes = maxBytes;
+        nBytes = 0;
+    }
+
+    /**
+     * Writes the specified byte to this byte array output stream.
+     * Any bytes after the first maxBytes will be ignored.
+     *
+     * @param   b   the byte to be written.
+     */
+    public synchronized void write(int b) {
+        if (nBytes < maxBytes) {
+            ++nBytes;
+            super.write(b);
+        }
+    }
+
+    /**
+     * Writes <code>len</code> bytes from the specified byte array
+     * starting at offset <code>off</code> to this byte array output stream.
+     * Any bytes after the first maxBytes will be ignored.
+     *
+     * @param   b     the data.
+     * @param   off   the start offset in the data.
+     * @param   len   the number of bytes to write.
+     */
+    public synchronized void write(byte b[], int off, int len) {
+        int storable = Math.min(maxBytes - nBytes, len);
+        if (storable > 0) {
+            nBytes += storable;
+            super.write(b, off, storable);
+        }
+    }
+
+
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/NotAuthorizedException.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/NotAuthorizedException.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/NotAuthorizedException.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/NotAuthorizedException.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,27 @@
+/*
+ * 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.hcatalog.templeton;
+
+/**
+ * Simple "user not found" type exception.
+ */
+public class NotAuthorizedException extends SimpleWebException {
+    public NotAuthorizedException(String msg) {
+        super(401, msg);
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PartitionDesc.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PartitionDesc.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PartitionDesc.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PartitionDesc.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hcatalog.templeton;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * A description of the partition to create.
+ */
+@XmlRootElement
+public class PartitionDesc extends GroupPermissionsDesc {
+    public String partition;
+    public String location;
+    public boolean ifNotExists = false;
+
+    public PartitionDesc() {}
+
+    public String toString() {
+        return String.format("PartitionDesc(partition=%s, location=%s, ifNotExists=%s)",
+                             partition, location, ifNotExists);
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PigDelegator.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PigDelegator.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PigDelegator.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/PigDelegator.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,94 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.commons.exec.ExecuteException;
+import org.apache.hcatalog.templeton.tool.TempletonUtils;
+
+/**
+ * Submit a Pig job.
+ *
+ * This is the backend of the pig web service.
+ */
+public class PigDelegator extends LauncherDelegator {
+    public PigDelegator(AppConfig appConf) {
+        super(appConf);
+    }
+
+    public EnqueueBean run(String user,
+                           String execute, String srcFile,
+                           List<String> pigArgs, String otherFiles,
+                           String statusdir, String callback, String completedUrl)
+        throws NotAuthorizedException, BadParam, BusyException, QueueException,
+        ExecuteException, IOException, InterruptedException
+    {
+        runAs = user;
+        List<String> args = makeArgs(execute,
+                                     srcFile, pigArgs,
+                                     otherFiles, statusdir, completedUrl);
+
+        return enqueueController(user, callback, args);
+    }
+
+    private List<String> makeArgs(String execute, String srcFile,
+                                  List<String> pigArgs, String otherFiles,
+                                  String statusdir, String completedUrl)
+        throws BadParam, IOException, InterruptedException
+    {
+        ArrayList<String> args = new ArrayList<String>();
+        try {
+            ArrayList<String> allFiles = new ArrayList<String>();
+            if (TempletonUtils.isset(srcFile))
+                allFiles.add(TempletonUtils.hadoopFsFilename
+                        (srcFile, appConf, runAs));
+            if (TempletonUtils.isset(otherFiles)) {
+                String[] ofs = TempletonUtils.hadoopFsListAsArray
+                        (otherFiles, appConf, runAs);
+                allFiles.addAll(Arrays.asList(ofs));
+            }
+
+            args.addAll(makeLauncherArgs(appConf, statusdir, completedUrl, allFiles));
+            args.add("-archives");
+            args.add(appConf.pigArchive());
+
+            args.add("--");
+            args.add(appConf.pigPath());
+            args.addAll(pigArgs);
+            if (TempletonUtils.isset(execute)) {
+                args.add("-execute");
+                args.add(execute);
+            } else if (TempletonUtils.isset(srcFile)) {
+                args.add("-file");
+                args.add(TempletonUtils.hadoopFsPath(srcFile, appConf, runAs)
+                        .getName());
+            }
+        } catch (FileNotFoundException e) {
+            throw new BadParam(e.getMessage());
+        } catch (URISyntaxException e) {
+            throw new BadParam(e.getMessage());
+        }
+
+        return args;
+    }
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueException.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueException.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueException.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueException.java Wed Jul 25 20:29:44 2012
@@ -0,0 +1,30 @@
+/*
+ * 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.hcatalog.templeton;
+
+import java.util.HashMap;
+
+/**
+ * Unable to queue the job
+ */
+public class QueueException extends SimpleWebException {
+    public QueueException(String msg) {
+        super(500, msg);
+    }
+
+}

Added: incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueStatusBean.java
URL: http://svn.apache.org/viewvc/incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueStatusBean.java?rev=1365722&view=auto
==============================================================================
--- incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueStatusBean.java (added)
+++ incubator/hcatalog/trunk/webhcat/svr/src/main/java/org/apache/hcatalog/templeton/QueueStatusBean.java Wed Jul 25 20:29:44 2012
@@ -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.hcatalog.templeton;
+
+import java.io.IOException;
+import org.apache.hadoop.mapred.JobStatus;
+import org.apache.hadoop.mapred.JobProfile;
+import org.apache.hcatalog.templeton.tool.JobState;
+
+/**
+ * QueueStatusBean - The results of an exec call.
+ */
+public class QueueStatusBean {
+    public JobStatus status;
+    public JobProfile profile;
+
+    public String  id;
+    public String  parentId;
+    public String  percentComplete;
+    public Long    exitValue;
+    public String  user;
+    public String  callback;
+    public String  completed;
+
+    public QueueStatusBean() {}
+
+    /**
+     * Create a new QueueStatusBean
+     *
+     * @param state      store job state
+     * @param status     job status
+     * @param profile    job profile
+     */
+    public QueueStatusBean(JobState state, JobStatus status, JobProfile profile)
+        throws IOException
+    {
+        this.status = status;
+        this.profile = profile;
+
+        id              = profile.getJobID().toString();
+        parentId        = state.getId();
+        if (id.equals(parentId))
+            parentId = null;
+        percentComplete = state.getPercentComplete();
+        exitValue       = state.getExitValue();
+        user            = state.getUser();
+        callback        = state.getCallback();
+        completed       = state.getCompleteStatus();
+    }
+}



Mime
View raw message