You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2009/01/22 01:21:18 UTC

svn commit: r736503 [2/4] - in /hadoop/hbase/trunk: ./ lib/ src/java/org/apache/hadoop/hbase/ src/java/org/apache/hadoop/hbase/io/ src/java/org/apache/hadoop/hbase/regionserver/ src/java/org/apache/hadoop/hbase/rest/ src/java/org/apache/hadoop/hbase/re...

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowHandler.java Wed Jan 21 16:21:16 2009
@@ -1,346 +0,0 @@
-package org.apache.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.io.BatchUpdate;
-import org.apache.hadoop.hbase.io.Cell;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.znerd.xmlenc.XMLOutputter;
-
-public class RowHandler extends GenericHandler {
-
-  public RowHandler(HBaseConfiguration conf, HBaseAdmin admin)
-	throws ServletException {
-		super(conf, admin);
-	}
-
-	public void doGet(HttpServletRequest request, HttpServletResponse response,
-      String[] pathSegments) throws ServletException, IOException {
-	  HTable table = getTable(pathSegments[0]);
-	  if (pathSegments[1].toLowerCase().equals(ROW)) {
-      // get a row
-      getRow(table, request, response, pathSegments);
-    } else {
-      doNotFound(response, "Not handled in RowHandler");
-    }
-  }
-
-  public void doPost(HttpServletRequest request, HttpServletResponse response,
-      String[] pathSegments) throws ServletException, IOException {
-    putRow(request, response, pathSegments);
-  }
-
-  public void doPut(HttpServletRequest request, HttpServletResponse response,
-      String[] pathSegments) throws ServletException, IOException {
-    doPost(request, response, pathSegments);
-  }
-
-  public void doDelete(HttpServletRequest request,
-      HttpServletResponse response, String[] pathSegments)
-      throws ServletException, IOException {
-    deleteRow(request, response, pathSegments);
-  }
-    
-  /*
-   * @param request
-   * @param response
-   * @param pathSegments info path split on the '/' character.  First segment
-   * is the tablename, second is 'row', and third is the row id.
-   * @throws IOException
-   * Retrieve a row in one of several output formats.
-   */
-  private void getRow(HTable table, final HttpServletRequest request,
-    final HttpServletResponse response, final String [] pathSegments)
-  throws IOException {
-    // pull the row key out of the path
-    byte[] row = Bytes.toBytes(URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING));
-
-    String timestampStr = null;
-    if (pathSegments.length == 4) {
-      // A timestamp has been supplied.
-      timestampStr = pathSegments[3];
-      if (timestampStr.equals("timestamps")) {
-        // Not supported in hbase just yet. TODO
-        doMethodNotAllowed(response, "Not yet supported by hbase");
-        return;
-      }
-    }
-    
-    String[] column_params = request.getParameterValues(COLUMN);
-    
-    byte[][] columns = null;
-    
-    if (column_params != null && column_params.length > 0) {
-      List<String> available_columns = new ArrayList<String>();
-      for (String column_param : column_params) {
-        if (column_param.length() > 0 && table.getTableDescriptor().hasFamily(Bytes.toBytes(column_param))) {
-          available_columns.add(column_param);
-        }
-      }
-      columns = Bytes.toByteArrays(available_columns.toArray(new String[0]));
-    }
-    
-    String[] version_params = request.getParameterValues(VERSION);
-    int version = 0;
-    if (version_params != null && version_params.length == 1) {
-      version = Integer.parseInt(version_params[0]);
-    }
-    
-    if (version > 0 && columns != null) {
-      Map<byte[], Cell[]> result = new TreeMap<byte [], Cell[]>(Bytes.BYTES_COMPARATOR);      
-      
-      for (byte[] col : columns) {
-        Cell[] cells = timestampStr == null ? table.get(row, col, version)
-                      : table.get(row, col, Long.parseLong(timestampStr), version);
-        if (cells != null) {
-          result.put(col, cells);
-        }
-      }
-      
-      if (result == null || result.size() == 0) {
-        doNotFound(response, "Row not found!");
-      } else {
-        switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
-        case XML:
-          outputRowWithMultiVersionsXml(request, response, result);
-          break;
-        case MIME:
-        default:
-          doNotAcceptable(response, "Unsupported Accept Header Content: "
-              + request.getHeader(CONTENT_TYPE));
-        }
-      }      
-    } else {
-      Map<byte[], Cell> result = timestampStr == null ? table.getRow(row, columns) : table.getRow(row, columns, Long.parseLong(timestampStr));
-      if (result == null || result.size() == 0) {
-        doNotFound(response, "Row not found!");
-      } else {
-        switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
-        case XML:
-          outputRowXml(request, response, result);
-          break;
-        case MIME:
-        default:
-          doNotAcceptable(response, "Unsupported Accept Header Content: "
-              + request.getHeader(CONTENT_TYPE));
-        }
-      }
-    }
-  }
-  
-  /*
-   * Output a row encoded as XML.
-   * @param response
-   * @param result
-   * @throws IOException
-   */
-  private void outputRowXml(final HttpServletRequest request, 
-      final HttpServletResponse response, final Map<byte [], Cell> result)
-  throws IOException {
-    setResponseHeader(response, result.size() > 0? 200: 204,
-        ContentType.XML.toString());
-    XMLOutputter outputter = getXMLOutputter(response.getWriter());
-    outputter.startTag(ROW);
-    doElement(outputter, "count", String.valueOf(result.size()));
-    outputColumnsXml(request, outputter, result);
-    outputter.endTag();
-    outputter.endDocument();
-    outputter.getWriter().close();
-  }
-  
-  private void outputRowWithMultiVersionsXml(final HttpServletRequest request, 
-      final HttpServletResponse response, final Map<byte[], Cell[]> result) 
-  throws IOException {
-    setResponseHeader(response, result.size() > 0? 200: 204,
-        ContentType.XML.toString());
-    XMLOutputter outputter = getXMLOutputter(response.getWriter());
-    outputter.startTag(ROW);
-    doElement(outputter, "count", String.valueOf(result.size()));    
-    outputColumnsWithMultiVersionsXml(request, outputter, result);
-    outputter.endTag();
-    outputter.endDocument();
-    outputter.getWriter().close();   
-  }
-  /*
-   * @param response
-   * @param result
-   * Output the results contained in result as a multipart/related response.
-   */
-  // private void outputRowMime(final HttpServletResponse response,
-  //     final Map<Text, Cell> result)
-  // throws IOException {
-  //   response.setStatus(result.size() > 0? 200: 204);
-  //   // This code ties me to the jetty server.
-  //   MultiPartResponse mpr = new MultiPartResponse(response);
-  //   // Content type should look like this for multipart:
-  //   // Content-type: multipart/related;start="<ro...@example.jaxws.sun.com>";type="application/xop+xml";boundary="uuid:94ebf1e6-7eb5-43f1-85f4-2615fc40c5d6";start-info="text/xml"
-  //   String ct = ContentType.MIME.toString() + ";charset=\"UTF-8\";boundary=\"" +
-  //     mpr.getBoundary() + "\"";
-  //   // Setting content type is broken.  I'm unable to set parameters on the
-  //   // content-type; They get stripped.  Can't set boundary, etc.
-  //   // response.addHeader("Content-Type", ct);
-  //   response.setContentType(ct);
-  //   outputColumnsMime(mpr, result);
-  //   mpr.close();
-  // }
-  
-  /*
-   * @param request
-   * @param response
-   * @param pathSegments
-   * Do a put based on the client request.
-   */
-  private void putRow(final HttpServletRequest request,
-    final HttpServletResponse response, final String [] pathSegments)
-  throws IOException, ServletException {
-    HTable table = getTable(pathSegments[0]);
-
-    // pull the row key out of the path
-    String row = URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING);
-    
-    switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
-      case XML:
-        putRowXml(table, row, request, response, pathSegments);
-        break;
-      case MIME:
-        doNotAcceptable(response, "Don't support multipart/related yet...");
-        break;
-      default:
-        doNotAcceptable(response, "Unsupported Accept Header Content: " +
-          request.getHeader(CONTENT_TYPE));
-    }
-  }
-
-  /*
-   * @param request
-   * @param response
-   * @param pathSegments
-   * Decode supplied XML and do a put to Hbase.
-   */
-  private void putRowXml(HTable table, String row, 
-    final HttpServletRequest request, final HttpServletResponse response, 
-    final String [] pathSegments)
-  throws IOException, ServletException{
-
-    DocumentBuilderFactory docBuilderFactory 
-      = DocumentBuilderFactory.newInstance();  
-    //ignore all comments inside the xml file
-    docBuilderFactory.setIgnoringComments(true);
-
-    DocumentBuilder builder = null;
-    Document doc = null;
-    
-    String timestamp = pathSegments.length >= 4 ? pathSegments[3] : null;
-    
-    try{
-      builder = docBuilderFactory.newDocumentBuilder();
-      doc = builder.parse(request.getInputStream());
-    } catch (javax.xml.parsers.ParserConfigurationException e) {
-      throw new ServletException(e);
-    } catch (org.xml.sax.SAXException e){
-      throw new ServletException(e);
-    }
-
-    BatchUpdate batchUpdate;
-    
-    try{
-      // start an update
-      batchUpdate = timestamp == null ? 
-        new BatchUpdate(row) : new BatchUpdate(row, Long.parseLong(timestamp));
-
-      // set the columns from the xml
-      NodeList columns = doc.getElementsByTagName("column");
-
-      for(int i = 0; i < columns.getLength(); i++){
-        // get the current column element we're working on
-        Element column = (Element)columns.item(i);
-
-        // extract the name and value children
-        Node name_node = column.getElementsByTagName("name").item(0);
-        String name = name_node.getFirstChild().getNodeValue();
-
-        Node value_node = column.getElementsByTagName("value").item(0);
-
-        byte[] value = new byte[0];
-        
-        // for some reason there's no value here. probably indicates that
-        // the consumer passed a null as the cell value.
-        if(value_node.getFirstChild() != null && 
-          value_node.getFirstChild().getNodeValue() != null){
-          // decode the base64'd value
-          value = org.apache.hadoop.hbase.util.Base64.decode(
-            value_node.getFirstChild().getNodeValue());
-        }
-
-        // put the value
-        batchUpdate.put(name, value);
-      }
-
-      // commit the update
-      table.commit(batchUpdate);
-      
-      // respond with a 200
-      response.setStatus(200);      
-    }
-    catch(Exception e){
-      throw new ServletException(e);
-    }
-  }
-  
-  /*
-   * @param request
-   * @param response
-   * @param pathSegments
-   * Delete some or all cells for a row.
-   */
-   private void deleteRow(final HttpServletRequest request,
-    final HttpServletResponse response, final String [] pathSegments)
-   throws IOException, ServletException {
-    // grab the table we're operating on
-    HTable table = getTable(getTableName(pathSegments));
-    
-    // pull the row key out of the path
-    String row = URLDecoder.decode(pathSegments[2], HConstants.UTF8_ENCODING);
-
-    String[] columns = request.getParameterValues(COLUMN);
-        
-    // hack - we'll actually test for the presence of the timestamp parameter
-    // eventually
-    boolean timestamp_present = false;
-    if(timestamp_present){ // do a timestamp-aware delete
-      doMethodNotAllowed(response, "DELETE with a timestamp not implemented!");
-    }
-    else{ // ignore timestamps
-      if(columns == null || columns.length == 0){
-        // retrieve all the columns
-        doMethodNotAllowed(response,
-          "DELETE without specified columns not implemented!");
-      } else{
-        // delete each column in turn      
-        for(int i = 0; i < columns.length; i++){
-          table.deleteAll(row, columns[i]);
-        }
-      }
-      response.setStatus(202);
-    }
-  }
-}

Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/RowModel.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.rest;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.io.BatchUpdate;
+import org.apache.hadoop.hbase.io.RowResult;
+import org.apache.hadoop.hbase.rest.descriptors.TimestampsDescriptor;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+
+public class RowModel extends AbstractModel {
+
+  @SuppressWarnings("unused")
+  private Log LOG = LogFactory.getLog(RowModel.class);
+
+  public RowModel(HBaseConfiguration conf, HBaseAdmin admin) {
+    super.initialize(conf, admin);
+  }
+
+  public RowResult get(byte[] tableName, byte[] rowName)
+      throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      return table.getRow(rowName);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public RowResult get(byte[] tableName, byte[] rowName, byte[][] columns)
+      throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      return table.getRow(rowName, columns);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public RowResult get(byte[] tableName, byte[] rowName, byte[][] columns,
+      long timestamp) throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      return table.getRow(rowName, columns, timestamp);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public RowResult get(byte[] tableName, byte[] rowName, long timestamp)
+      throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      return table.getRow(rowName, timestamp);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public TimestampsDescriptor getTimestamps(
+      @SuppressWarnings("unused") byte[] tableName,
+      @SuppressWarnings("unused") byte[] rowName) throws HBaseRestException {
+    // try {
+    // TimestampsDescriptor tsd = new TimestampsDescriptor();
+    // HTable table = new HTable(tableName);
+    // RowResult row = table.getRow(rowName);
+
+    throw new HBaseRestException("operation currently unsupported");
+
+    // } catch (IOException e) {
+    // throw new HBaseRestException("Error finding timestamps for row: "
+    // + Bytes.toString(rowName), e);
+    // }
+
+  }
+
+  public void post(byte[] tableName, BatchUpdate b) throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      table.commit(b);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public void post(byte[] tableName, List<BatchUpdate> b)
+      throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      table.commit(b);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public void delete(byte[] tableName, byte[] rowName)
+      throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      table.deleteAll(rowName);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public void delete(byte[] tableName, byte[] rowName, byte[][] columns) throws HBaseRestException {
+    try {
+      HTable table = new HTable(tableName);
+      for (byte[] column : columns) {
+        table.deleteAll(rowName, column);
+      }
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+}

Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerController.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,358 @@
+/**
+ * Copyright 2007 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.rest;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.filter.RowFilterInterface;
+import org.apache.hadoop.hbase.filter.RowFilterSet;
+import org.apache.hadoop.hbase.filter.StopRowFilter;
+import org.apache.hadoop.hbase.filter.WhileMatchRowFilter;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerDescriptor;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.filter.FilterFactory;
+import org.apache.hadoop.hbase.rest.parser.IHBaseRestParser;
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * 
+ */
+public class ScannerController extends AbstractController {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#delete(org.apache.hadoop
+   * .hbase.rest.Status, byte[][], java.util.Map)
+   */
+  @Override
+  public void delete(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap) throws HBaseRestException {
+    ScannerModel innerModel = this.getModel();
+    if (pathSegments.length == 3
+        && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+            RESTConstants.SCANNER)) {
+      // get the scannerId
+      Integer scannerId = null;
+      String scannerIdString = new String(pathSegments[2]);
+      if (!Pattern.matches("^\\d+$", scannerIdString)) {
+        throw new HBaseRestException(
+            "the scannerid in the path and must be an integer");
+      }
+      scannerId = Integer.parseInt(scannerIdString);
+
+      try {
+        innerModel.scannerClose(scannerId);
+        s.setOK();
+      } catch (HBaseRestException e) {
+        s.setNotFound();
+      }
+    } else {
+      s.setBadRequest("invalid query");
+    }
+    s.respond();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#generateModel(org.apache
+   * .hadoop.hbase.HBaseConfiguration,
+   * org.apache.hadoop.hbase.client.HBaseAdmin)
+   */
+  @Override
+  protected AbstractModel generateModel(HBaseConfiguration conf, HBaseAdmin a) {
+    return new ScannerModel(conf, a);
+  }
+
+  protected ScannerModel getModel() {
+    return (ScannerModel) model;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#get(org.apache.hadoop.hbase
+   * .rest.Status, byte[][], java.util.Map)
+   */
+  @Override
+  public void get(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap) throws HBaseRestException {
+
+    s.setBadRequest("invalid query");
+    s.respond();
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#post(org.apache.hadoop.
+   * hbase.rest.Status, byte[][], java.util.Map, byte[],
+   * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+   */
+  @Override
+  public void post(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+      throws HBaseRestException {
+    ScannerModel innerModel = this.getModel();
+    byte[] tableName;
+    tableName = pathSegments[0];
+
+    // Otherwise we interpret this request as a scanner request.
+    if (pathSegments.length == 2
+        && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+            RESTConstants.SCANNER)) { // new scanner request
+      ScannerDescriptor sd = this.getScannerDescriptor(queryMap);
+      s.setScannerCreated(createScanner(innerModel, tableName, sd));
+    } else if (pathSegments.length == 3
+        && Bytes.toString(pathSegments[1]).toLowerCase().equals(
+            RESTConstants.SCANNER)) { // open scanner request
+      // first see if the limit variable is present
+      Long numRows = 1L;
+      String[] numRowsString = queryMap.get(RESTConstants.LIMIT);
+      if (numRowsString != null && Pattern.matches("^\\d+$", numRowsString[0])) {
+        numRows = Long.parseLong(numRowsString[0]);
+      }
+      // get the scannerId
+      Integer scannerId = null;
+      String scannerIdString = new String(pathSegments[2]);
+      if (!Pattern.matches("^\\d+$", scannerIdString)) {
+        throw new HBaseRestException(
+            "the scannerid in the path and must be an integer");
+      }
+      scannerId = Integer.parseInt(scannerIdString);
+
+      try {
+        s.setOK(innerModel.scannerGet(scannerId, numRows));
+      } catch (HBaseRestException e) {
+        s.setNotFound();
+      }
+    } else {
+      s.setBadRequest("Unknown Query.");
+    }
+    s.respond();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#put(org.apache.hadoop.hbase
+   * .rest.Status, byte[][], java.util.Map, byte[],
+   * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+   */
+  @Override
+  public void put(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+      throws HBaseRestException {
+
+    s.setBadRequest("invalid query");
+    s.respond();
+
+  }
+
+  private ScannerDescriptor getScannerDescriptor(Map<String, String[]> queryMap) {
+    long timestamp = 0L;
+    byte[] startRow = null;
+    byte[] stopRow = null;
+    String filters = null;
+
+    String[] timeStampString = queryMap.get(RESTConstants.SCANNER_TIMESTAMP);
+    if (timeStampString != null && timeStampString.length == 1) {
+      timestamp = Long.parseLong(timeStampString[0]);
+    }
+
+    String[] startRowString = queryMap.get(RESTConstants.SCANNER_START_ROW);
+    if (startRowString != null && startRowString.length == 1) {
+      startRow = Bytes.toBytes(startRowString[0]);
+    }
+
+    String[] stopRowString = queryMap.get(RESTConstants.SCANNER_STOP_ROW);
+    if (stopRowString != null && stopRowString.length == 1) {
+      stopRow = Bytes.toBytes(stopRowString[0]);
+    }
+
+    String[] filtersStrings = queryMap.get(RESTConstants.SCANNER_FILTER);
+    if (filtersStrings != null && filtersStrings.length > 0) {
+      filters = "";
+      for (@SuppressWarnings("unused")
+      String filter : filtersStrings) {
+        // TODO filters are not hooked up yet... And the String should probably
+        // be changed to a set
+      }
+    }
+    return new ScannerDescriptor(this.getColumnsFromQueryMap(queryMap),
+        timestamp, startRow, stopRow, filters);
+  }
+
+  protected ScannerIdentifier createScanner(ScannerModel innerModel,
+      byte[] tableName, ScannerDescriptor scannerDescriptor)
+      throws HBaseRestException {
+
+    RowFilterInterface filterSet = null;
+
+    // Might want to change this. I am doing this so that I can use
+    // a switch statement that is more efficient.
+    int switchInt = 0;
+    if (scannerDescriptor.getColumns() != null
+        && scannerDescriptor.getColumns().length > 0) {
+      switchInt += 1;
+    }
+    switchInt += (scannerDescriptor.getTimestamp() != 0L) ? (1 << 1) : 0;
+    switchInt += (scannerDescriptor.getStartRow().length > 0) ? (1 << 2) : 0;
+    switchInt += (scannerDescriptor.getStopRow().length > 0) ? (1 << 3) : 0;
+    if (scannerDescriptor.getFilters() != null
+        && !scannerDescriptor.getFilters().equals("")) {
+      switchInt += (scannerDescriptor.getFilters() != null) ? (1 << 4) : 0;
+      filterSet = unionFilters(scannerDescriptor.getFilters());
+    }
+
+    return scannerSwitch(switchInt, innerModel, tableName, scannerDescriptor
+        .getColumns(), scannerDescriptor.getTimestamp(), scannerDescriptor
+        .getStartRow(), scannerDescriptor.getStopRow(), filterSet);
+  }
+
+  public ScannerIdentifier scannerSwitch(int switchInt,
+      ScannerModel innerModel, byte[] tableName, byte[][] columns,
+      long timestamp, byte[] startRow, byte[] stopRow,
+      RowFilterInterface filterSet) throws HBaseRestException {
+    switch (switchInt) {
+    case 0:
+      return innerModel.scannerOpen(tableName);
+    case 1:
+      return innerModel.scannerOpen(tableName, columns);
+    case 2:
+      return innerModel.scannerOpen(tableName, timestamp);
+    case 3:
+      return innerModel.scannerOpen(tableName, columns, timestamp);
+    case 4:
+      return innerModel.scannerOpen(tableName, startRow);
+    case 5:
+      return innerModel.scannerOpen(tableName, columns, startRow);
+    case 6:
+      return innerModel.scannerOpen(tableName, startRow, timestamp);
+    case 7:
+      return innerModel.scannerOpen(tableName, columns, startRow, timestamp);
+    case 8:
+      return innerModel.scannerOpen(tableName, getStopRow(stopRow));
+    case 9:
+      return innerModel.scannerOpen(tableName, columns, getStopRow(stopRow));
+    case 10:
+      return innerModel.scannerOpen(tableName, timestamp, getStopRow(stopRow));
+    case 11:
+      return innerModel.scannerOpen(tableName, columns, timestamp,
+          getStopRow(stopRow));
+    case 12:
+      return innerModel.scannerOpen(tableName, startRow, getStopRow(stopRow));
+    case 13:
+      return innerModel.scannerOpen(tableName, columns, startRow,
+          getStopRow(stopRow));
+    case 14:
+      return innerModel.scannerOpen(tableName, startRow, timestamp,
+          getStopRow(stopRow));
+    case 15:
+      return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+          getStopRow(stopRow));
+    case 16:
+      return innerModel.scannerOpen(tableName, filterSet);
+    case 17:
+      return innerModel.scannerOpen(tableName, columns, filterSet);
+    case 18:
+      return innerModel.scannerOpen(tableName, timestamp, filterSet);
+    case 19:
+      return innerModel.scannerOpen(tableName, columns, timestamp, filterSet);
+    case 20:
+      return innerModel.scannerOpen(tableName, startRow, filterSet);
+    case 21:
+      return innerModel.scannerOpen(tableName, columns, startRow, filterSet);
+    case 22:
+      return innerModel.scannerOpen(tableName, startRow, timestamp, filterSet);
+    case 23:
+      return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+          filterSet);
+    case 24:
+      return innerModel.scannerOpen(tableName, getStopRowUnionFilter(stopRow,
+          filterSet));
+    case 25:
+      return innerModel.scannerOpen(tableName, columns, getStopRowUnionFilter(
+          stopRow, filterSet));
+    case 26:
+      return innerModel.scannerOpen(tableName, timestamp,
+          getStopRowUnionFilter(stopRow, filterSet));
+    case 27:
+      return innerModel.scannerOpen(tableName, columns, timestamp,
+          getStopRowUnionFilter(stopRow, filterSet));
+    case 28:
+      return innerModel.scannerOpen(tableName, startRow, getStopRowUnionFilter(
+          stopRow, filterSet));
+    case 29:
+      return innerModel.scannerOpen(tableName, columns, startRow,
+          getStopRowUnionFilter(stopRow, filterSet));
+    case 30:
+      return innerModel.scannerOpen(tableName, startRow, timestamp,
+          getStopRowUnionFilter(stopRow, filterSet));
+    case 31:
+      return innerModel.scannerOpen(tableName, columns, startRow, timestamp,
+          getStopRowUnionFilter(stopRow, filterSet));
+    default:
+      return null;
+    }
+  }
+
+  protected RowFilterInterface getStopRow(byte[] stopRow) {
+    return new WhileMatchRowFilter(new StopRowFilter(stopRow));
+  }
+
+  protected RowFilterInterface getStopRowUnionFilter(byte[] stopRow,
+      RowFilterInterface filter) {
+    Set<RowFilterInterface> filterSet = new HashSet<RowFilterInterface>();
+    filterSet.add(getStopRow(stopRow));
+    filterSet.add(filter);
+    return new RowFilterSet(filterSet);
+  }
+
+  /**
+   * Given a list of filters in JSON string form, returns a RowSetFilter that
+   * returns true if all input filters return true on a Row (aka an AND
+   * statement).
+   * 
+   * @param filters
+   *          array of input filters in a JSON String
+   * @return RowSetFilter with all input filters in an AND Statement
+   * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+   */
+  protected RowFilterInterface unionFilters(String filters)
+      throws HBaseRestException {
+    FilterFactory f = RESTConstants.filterFactories.get("RowFilterSet");
+    return f.getFilterFromJSON(filters);
+  }
+
+}

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerHandler.java Wed Jan 21 16:21:16 2009
@@ -1,339 +0,0 @@
-/**
- * Copyright 2007 The Apache Software Foundation
- *
- * 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.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.Scanner;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.hadoop.hbase.util.JenkinsHash;
-import org.apache.hadoop.hbase.io.Cell;
-import org.apache.hadoop.hbase.io.RowResult;
-import org.znerd.xmlenc.XMLOutputter;
-
-/**
- * ScannderHandler fields all scanner related requests. 
- */
-public class ScannerHandler extends GenericHandler {
-  private static final String ROWS = "rows";
-  
-  public ScannerHandler(HBaseConfiguration conf, HBaseAdmin admin) 
-  throws ServletException{
-    super(conf, admin);
-  }
-    
-  private class ScannerRecord {
-    private final Scanner scanner;
-    private List<RowResult> nextRows;
-    
-    ScannerRecord(final Scanner s) {
-      this.scanner = s;
-      nextRows = new ArrayList<RowResult>();
-    }
-  
-    public Scanner getScanner() {
-      return this.scanner;
-    }
-    
-    public boolean hasNext(int nbRows) throws IOException {
-      if (nextRows.size() < nbRows) {
-        RowResult[] results = scanner.next(nbRows - nextRows.size());
-        for (RowResult result : results) {
-          nextRows.add(result);
-        }
-        return nextRows.size() > 0;
-      } else {
-        return true;
-      }
-    }
-    
-    /**
-     * Call next on the scanner.
-     * @return Null if finished, RowResult otherwise
-     * @throws IOException
-     */
-    public RowResult[] next(int nbRows) throws IOException {
-      if (!hasNext(nbRows)) {
-        return null;
-      }
-      RowResult[] temp = nextRows.toArray(new RowResult[nextRows.size()]);
-      nextRows.clear();
-      return temp;
-    }
-  }
-  
-  /*
-   * Map of outstanding scanners keyed by scannerid.
-   */
-  private final Map<String, ScannerRecord> scanners =
-    new HashMap<String, ScannerRecord>();
-  
-  public void doGet(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    doMethodNotAllowed(response, "GET to a scanner not supported.");
-  }
-  
-  public void doPost(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    if (pathSegments.length == 2) {
-      // trying to create a scanner
-      openScanner(request, response, pathSegments);
-    }
-    else if (pathSegments.length == 3) {
-      // advancing a scanner
-      getScanner(request, response, pathSegments[2]);
-    }
-    else{
-      doNotFound(response, "No handler for request");
-    }
-  }
-  
-  public void doPut(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    doPost(request, response, pathSegments);
-  }
-  
-  public void doDelete(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    deleteScanner(response, pathSegments[2]);
-  }
-  
-  /*
-   * Advance scanner and return current position.
-   * @param request
-   * @param response
-   * @param scannerid
-   * @throws IOException
-   */
-  private void getScanner(final HttpServletRequest request,
-      final HttpServletResponse response, final String scannerid)
-  throws IOException {
-    ScannerRecord sr = this.scanners.get(scannerid);
-    if (sr == null) {
-      doNotFound(response, "No such scanner.");
-      return;
-    }
-
-    String limitString = request.getParameter(LIMIT);
-    int limit = 1;
-    if (limitString != null && limitString.length() > 0) {
-      limit = Integer.valueOf(limitString);
-    }
-    if (sr.hasNext(limit)) {
-      switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
-        case XML:
-          outputScannerEntryXML(response, sr, limit);
-          break;
-        case MIME:
-/*          outputScannerEntryMime(response, sr);*/
-          doNotAcceptable(response);
-          break;
-        default:
-          doNotAcceptable(response);
-      }
-    }
-    else{
-      this.scanners.remove(scannerid);
-      doNotFound(response, "Scanner is expended");
-    }
-  }
-
-  private void outputScannerEntryXML(final HttpServletResponse response,
-      final ScannerRecord sr, int limit)
-  throws IOException {    
-    // respond with a 200 and Content-type: text/xml
-    setResponseHeader(response, 200, ContentType.XML.toString());
-    
-    // setup an xml outputter
-    XMLOutputter outputter = getXMLOutputter(response.getWriter());
-    
-    boolean rows = false;
-    
-    if (limit > 1) {
-      outputter.startTag(ROWS);
-      rows = true;
-    }
-    
-    RowResult[] rowResults = sr.next(limit);
-    
-    for (RowResult rowResult: rowResults) {
-      outputter.startTag(ROW);
-      
-      // write the row key
-      doElement(outputter, "name", 
-        org.apache.hadoop.hbase.util.Base64.encodeBytes(rowResult.getRow()));
-      
-      outputColumnsXml(outputter, rowResult);
-      outputter.endTag();
-    }
-    
-    if (rows) {
-      outputter.endTag();
-    }
-    
-    outputter.endDocument();
-    outputter.getWriter().close();
-  }
-
-  // private void outputScannerEntryMime(final HttpServletResponse response,
-  //   final ScannerRecord sr)
-  // throws IOException {
-  //   response.setStatus(200);
-  //   // This code ties me to the jetty server.
-  //   MultiPartResponse mpr = new MultiPartResponse(response);
-  //   // Content type should look like this for multipart:
-  //   // Content-type: multipart/related;start="<ro...@example.jaxws.sun.com>";type="application/xop+xml";boundary="uuid:94ebf1e6-7eb5-43f1-85f4-2615fc40c5d6";start-info="text/xml"
-  //   String ct = ContentType.MIME.toString() + ";charset=\"UTF-8\";boundary=\"" +
-  //     mpr.getBoundary() + "\"";
-  //   // Setting content type is broken.  I'm unable to set parameters on the
-  //   // content-type; They get stripped.  Can't set boundary, etc.
-  //   // response.addHeader("Content-Type", ct);
-  //   response.setContentType(ct);
-  //   // Write row, key-column and timestamp each in its own part.
-  //   mpr.startPart("application/octet-stream",
-  //       new String [] {"Content-Description: row",
-  //         "Content-Transfer-Encoding: binary",
-  //         "Content-Length: " + sr.getKey().getRow().getBytes().length});
-  //   mpr.getOut().write(sr.getKey().getRow().getBytes());
-  // 
-  //   // Usually key-column is empty when scanning.
-  //   if (sr.getKey().getColumn() != null &&
-  //       sr.getKey().getColumn().getLength() > 0) {
-  //     mpr.startPart("application/octet-stream",
-  //       new String [] {"Content-Description: key-column",
-  //         "Content-Transfer-Encoding: binary",
-  //         "Content-Length: " + sr.getKey().getColumn().getBytes().length});
-  //   }
-  //   mpr.getOut().write(sr.getKey().getColumn().getBytes());
-  //   // TODO: Fix. Need to write out the timestamp in the ordained timestamp
-  //   // format.
-  //   byte [] timestampBytes = Long.toString(sr.getKey().getTimestamp()).getBytes();
-  //   mpr.startPart("application/octet-stream",
-  //       new String [] {"Content-Description: timestamp",
-  //         "Content-Transfer-Encoding: binary",
-  //         "Content-Length: " + timestampBytes.length});
-  //   mpr.getOut().write(timestampBytes);
-  //   // Write out columns
-  //   outputColumnsMime(mpr, sr.getValue());
-  //   mpr.close();
-  // }
-  
-  /*
-   * Create scanner
-   * @param request
-   * @param response
-   * @param pathSegments
-   * @throws IOException
-   */
-  private void openScanner(final HttpServletRequest request,
-      final HttpServletResponse response, final String [] pathSegments)
-  throws IOException, ServletException {
-    // get the table
-    HTable table = getTable(getTableName(pathSegments));
-    
-    // get the list of columns we're supposed to interact with
-    String[] raw_columns = request.getParameterValues(COLUMN);
-    byte [][] columns = null;
-    
-    if (raw_columns != null) {
-      columns = new byte [raw_columns.length][];
-      for (int i = 0; i < raw_columns.length; i++) {
-        // I think this decoding is redundant.
-        columns[i] =
-          Bytes.toBytes(URLDecoder.decode(raw_columns[i], HConstants.UTF8_ENCODING));
-      }
-    } else {
-      // TODO: Need to put into the scanner all of the table's column
-      // families.  TODO: Verify this returns all rows.  For now just fail.
-      doMethodNotAllowed(response, "Unspecified columns parameter currently not supported!");
-      return;
-    }
-
-    // TODO: Parse according to the timestamp format we agree on.    
-    String raw_ts = request.getParameter(TIMESTAMP);
-
-    // TODO: Are these decodings redundant?
-    byte [] startRow = request.getParameter(START_ROW) == null?
-      HConstants.EMPTY_START_ROW:
-      Bytes.toBytes(URLDecoder.decode(request.getParameter(START_ROW),
-        HConstants.UTF8_ENCODING));
-    // Empty start row is same value as empty end row.
-    byte [] endRow = request.getParameter(END_ROW) == null?
-      HConstants.EMPTY_START_ROW:
-      Bytes.toBytes(URLDecoder.decode(request.getParameter(END_ROW),
-        HConstants.UTF8_ENCODING));
-
-    Scanner scanner = (request.getParameter(END_ROW) == null)?
-       table.getScanner(columns, startRow):
-       table.getScanner(columns, startRow, endRow);
-    
-    // Make a scanner id by hashing the object toString value (object name +
-    // an id).  Will make identifier less burdensome and more url friendly.
-    String scannerid =
-      Integer.toHexString(JenkinsHash.getInstance().hash(scanner.toString().getBytes(), -1));
-    ScannerRecord sr = new ScannerRecord(scanner);
-    
-    // store the scanner for subsequent requests
-    this.scanners.put(scannerid, sr);
-    
-    // set a 201 (Created) header and a Location pointing to the new
-    // scanner
-    response.setStatus(201);
-    response.addHeader("Location", request.getContextPath() + "/" +
-      pathSegments[0] + "/" + pathSegments[1] + "/" + scannerid);
-    response.getOutputStream().close();
-  }
-
-  /*
-   * Delete scanner
-   * @param response
-   * @param scannerid
-   * @throws IOException
-   */
-  private void deleteScanner(final HttpServletResponse response,
-      final String scannerid)
-  throws IOException, ServletException {
-    ScannerRecord sr = this.scanners.remove(scannerid);
-    if (sr == null) {
-      doNotFound(response, "No such scanner");
-    } else {
-      sr.getScanner().close();
-      response.setStatus(200);
-      response.getOutputStream().close();
-    }
-  }
-}

Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/ScannerModel.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,282 @@
+/**
+ * Copyright 2007 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.rest;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Scanner;
+import org.apache.hadoop.hbase.filter.RowFilterInterface;
+import org.apache.hadoop.hbase.io.RowResult;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+
+/**
+ * 
+ */
+public class ScannerModel extends AbstractModel {
+
+  @SuppressWarnings("unused")
+  private Log LOG = LogFactory.getLog(TableModel.class);
+
+  public ScannerModel(HBaseConfiguration config, HBaseAdmin admin) {
+    super.initialize(config, admin);
+  }
+  
+  //
+  // Normal Scanner
+  //
+  protected static class ScannerMaster {
+
+    protected static Map<Integer, Scanner> scannerMap = new ConcurrentHashMap<Integer, Scanner>();
+    protected static AtomicInteger nextScannerId = new AtomicInteger(1);
+
+    public Integer addScanner(Scanner scanner) {
+      Integer i = new Integer(nextScannerId.getAndIncrement());
+      scannerMap.put(i, scanner);
+      return i;
+    }
+
+    public Scanner getScanner(Integer id) {
+      return scannerMap.get(id);
+    }
+
+    public Scanner removeScanner(Integer id) {
+      return scannerMap.remove(id);
+    }
+
+    /**
+     * @param id
+     *          id of scanner to close
+     */
+    public void scannerClose(Integer id) {
+      Scanner s = scannerMap.remove(id);
+      s.close();
+    }
+  }
+
+  protected static ScannerMaster scannerMaster = new ScannerMaster();
+
+  /**
+   * returns the next numResults RowResults from the Scaner mapped to Integer
+   * id. If the end of the table is reached, the scanner is closed and all
+   * succesfully retrieved rows are returned.
+   * 
+   * @param id
+   *          id target scanner is mapped to.
+   * @param numRows
+   *          number of results to return.
+   * @return all successfully retrieved rows.
+   * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+   */
+  public RowResult[] scannerGet(Integer id, Long numRows)
+      throws HBaseRestException {
+    try {
+      ArrayList<RowResult> a;
+      Scanner s;
+      RowResult r;
+
+      a = new ArrayList<RowResult>();
+      s = scannerMaster.getScanner(id);
+
+      if (s == null) {
+        throw new HBaseRestException("ScannerId: " + id
+            + " is unavailable.  Please create a new scanner");
+      }
+
+      for (int i = 0; i < numRows; i++) {
+        if ((r = s.next()) != null) {
+          a.add(r);
+        } else {
+          scannerMaster.scannerClose(id);
+          break;
+        }
+      }
+
+      return a.toArray(new RowResult[0]);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  /**
+   * Returns all rows inbetween the scanners current position and the end of the
+   * table.
+   * 
+   * @param id
+   *          id of scanner to use
+   * @return all rows till end of table
+   * @throws org.apache.hadoop.hbase.rest.exception.HBaseRestException
+   */
+  public RowResult[] scannerGet(Integer id) throws HBaseRestException {
+    try {
+      ArrayList<RowResult> a;
+      Scanner s;
+      RowResult r;
+
+      a = new ArrayList<RowResult>();
+      s = scannerMaster.getScanner(id);
+
+      while ((r = s.next()) != null) {
+        a.add(r);
+      }
+
+      scannerMaster.scannerClose(id);
+
+      return a.toArray(new RowResult[0]);
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public boolean scannerClose(Integer id) throws HBaseRestException {
+    Scanner s = scannerMaster.removeScanner(id);
+
+    if (s == null) {
+      throw new HBaseRestException("Scanner id: " + id + " does not exist");
+    }
+    return true;
+  }
+
+  // Scanner Open Methods
+  // No Columns
+  public ScannerIdentifier scannerOpen(byte[] tableName)
+      throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName));
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, long timestamp)
+      throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), timestamp);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow)
+      throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), startRow);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+      long timestamp) throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), startRow, timestamp);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName,
+      RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), filter);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, long timestamp,
+      RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), timestamp, filter);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+      RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), startRow, filter);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[] startRow,
+      long timestamp, RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, getColumns(tableName), startRow, timestamp,
+        filter);
+  }
+
+  // With Columns
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      long timestamp) throws HBaseRestException {
+    try {
+      HTable table;
+      table = new HTable(tableName);
+      return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+          columns, HConstants.EMPTY_START_ROW, timestamp)));
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns)
+      throws HBaseRestException {
+    return scannerOpen(tableName, columns, HConstants.LATEST_TIMESTAMP);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      byte[] startRow, long timestamp) throws HBaseRestException {
+    try {
+      HTable table;
+      table = new HTable(tableName);
+      return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+          columns, startRow, timestamp)));
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      byte[] startRow) throws HBaseRestException {
+    return scannerOpen(tableName, columns, startRow,
+        HConstants.LATEST_TIMESTAMP);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      long timestamp, RowFilterInterface filter) throws HBaseRestException {
+    try {
+      HTable table;
+      table = new HTable(tableName);
+      return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+          columns, HConstants.EMPTY_START_ROW, timestamp, filter)));
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, columns, HConstants.LATEST_TIMESTAMP, filter);
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      byte[] startRow, long timestamp, RowFilterInterface filter)
+      throws HBaseRestException {
+    try {
+      HTable table;
+      table = new HTable(tableName);
+      return new ScannerIdentifier(scannerMaster.addScanner(table.getScanner(
+          columns, startRow, timestamp, filter)));
+    } catch (IOException e) {
+      throw new HBaseRestException(e);
+    }
+  }
+
+  public ScannerIdentifier scannerOpen(byte[] tableName, byte[][] columns,
+      byte[] startRow, RowFilterInterface filter) throws HBaseRestException {
+    return scannerOpen(tableName, columns, startRow,
+        HConstants.LATEST_TIMESTAMP, filter);
+  }
+  
+}

Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/Status.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,256 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.rest;
+
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.rest.descriptors.ScannerIdentifier;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.serializer.IRestSerializer;
+import org.apache.hadoop.hbase.rest.serializer.ISerializable;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import agilejson.TOJSON;
+
+public class Status {
+
+  @SuppressWarnings("unused")
+  private Log LOG = LogFactory.getLog(Status.class);
+
+  public static final HashMap<Integer, String> statNames = new HashMap<Integer, String>();
+
+  static {
+    statNames.put(HttpServletResponse.SC_CONTINUE, "continue");
+    statNames.put(HttpServletResponse.SC_SWITCHING_PROTOCOLS,
+        "switching protocols");
+    statNames.put(HttpServletResponse.SC_OK, "ok");
+    statNames.put(HttpServletResponse.SC_CREATED, "created");
+    statNames.put(HttpServletResponse.SC_ACCEPTED, "accepted");
+    statNames.put(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION,
+        "non-authoritative information");
+    statNames.put(HttpServletResponse.SC_NO_CONTENT, "no content");
+    statNames.put(HttpServletResponse.SC_RESET_CONTENT, "reset content");
+    statNames.put(HttpServletResponse.SC_PARTIAL_CONTENT, "partial content");
+    statNames.put(HttpServletResponse.SC_MULTIPLE_CHOICES, "multiple choices");
+    statNames
+        .put(HttpServletResponse.SC_MOVED_PERMANENTLY, "moved permanently");
+    statNames
+        .put(HttpServletResponse.SC_MOVED_TEMPORARILY, "moved temporarily");
+    statNames.put(HttpServletResponse.SC_FOUND, "found");
+    statNames.put(HttpServletResponse.SC_SEE_OTHER, "see other");
+    statNames.put(HttpServletResponse.SC_NOT_MODIFIED, "not modified");
+    statNames.put(HttpServletResponse.SC_USE_PROXY, "use proxy");
+    statNames.put(HttpServletResponse.SC_TEMPORARY_REDIRECT,
+        "temporary redirect");
+    statNames.put(HttpServletResponse.SC_BAD_REQUEST, "bad request");
+    statNames.put(HttpServletResponse.SC_UNAUTHORIZED, "unauthorized");
+    statNames.put(HttpServletResponse.SC_FORBIDDEN, "forbidden");
+    statNames.put(HttpServletResponse.SC_NOT_FOUND, "not found");
+    statNames.put(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
+        "method not allowed");
+    statNames.put(HttpServletResponse.SC_NOT_ACCEPTABLE, "not acceptable");
+    statNames.put(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED,
+        "proxy authentication required");
+    statNames.put(HttpServletResponse.SC_REQUEST_TIMEOUT, "request timeout");
+    statNames.put(HttpServletResponse.SC_CONFLICT, "conflict");
+    statNames.put(HttpServletResponse.SC_GONE, "gone");
+    statNames.put(HttpServletResponse.SC_LENGTH_REQUIRED, "length required");
+    statNames.put(HttpServletResponse.SC_PRECONDITION_FAILED,
+        "precondition failed");
+    statNames.put(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
+        "request entity too large");
+    statNames.put(HttpServletResponse.SC_REQUEST_URI_TOO_LONG,
+        "request uri too long");
+    statNames.put(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
+        "unsupported media type");
+    statNames.put(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE,
+        "requested range not satisfiable");
+    statNames.put(HttpServletResponse.SC_EXPECTATION_FAILED,
+        "expectation failed");
+    statNames.put(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+        "internal server error");
+    statNames.put(HttpServletResponse.SC_NOT_IMPLEMENTED, "not implemented");
+    statNames.put(HttpServletResponse.SC_BAD_GATEWAY, "bad gateway");
+    statNames.put(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
+        "service unavailable");
+    statNames.put(HttpServletResponse.SC_GATEWAY_TIMEOUT, "gateway timeout");
+    statNames.put(HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED,
+        "http version not supported");
+  }
+  protected int statusCode;
+  protected HttpServletResponse response;
+  protected Object message;
+  protected IRestSerializer serializer;
+  protected byte[][] pathSegments; 
+
+  public int getStatusCode() {
+    return statusCode;
+  }
+
+  @TOJSON
+  public Object getMessage() {
+    return message;
+  }
+
+  public static class StatusMessage implements ISerializable {
+    int statusCode;
+    boolean error;
+    Object reason;
+
+    public StatusMessage(int statusCode, boolean error, Object o) {
+      this.statusCode = statusCode;
+      this.error = error;
+      reason = o;
+    }
+
+    @TOJSON
+    public int getStatusCode() {
+      return statusCode;
+    }
+
+    @TOJSON
+    public boolean getError() {
+      return error;
+    }
+
+    @TOJSON
+    public Object getMessage() {
+      return reason;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hadoop.hbase.rest.xml.IOutputXML#toXML(org.apache.hadoop.hbase
+     * .rest.serializer.IRestSerializer)
+     */
+    public void restSerialize(IRestSerializer serializer)
+        throws HBaseRestException {
+      serializer.serializeStatusMessage(this);
+    }
+  }
+
+  public Status(HttpServletResponse r, IRestSerializer serializer, byte[][] bs) {
+    this.setOK();
+    this.response = r;
+    this.serializer = serializer;
+    this.pathSegments = bs;
+  }
+
+  // Good Messages
+  public void setOK() {
+    this.statusCode = HttpServletResponse.SC_OK;
+    this.message = new StatusMessage(HttpServletResponse.SC_OK, false, "success");
+  }
+
+  public void setOK(Object message) {
+    this.statusCode = HttpServletResponse.SC_OK;
+    this.message = message;
+  }
+  
+  public void setAccepted() {
+    this.statusCode = HttpServletResponse.SC_ACCEPTED;
+    this.message = new StatusMessage(HttpServletResponse.SC_ACCEPTED, false, "success");
+  }
+
+  public void setExists(boolean error) {
+    this.statusCode = HttpServletResponse.SC_CONFLICT;
+    this.message = new StatusMessage(statusCode, error, "table already exists");
+  }
+
+  public void setCreated() {
+    this.statusCode = HttpServletResponse.SC_CREATED;
+    this.setOK();
+  }  
+
+  public void setScannerCreated(ScannerIdentifier scannerIdentifier) {
+    this.statusCode = HttpServletResponse.SC_OK;
+    this.message = scannerIdentifier;
+    response.addHeader("Location", "/" + Bytes.toString(pathSegments[0])
+        + "/scanner/" + scannerIdentifier.getId());
+  }
+  // Bad Messages
+
+  public void setInternalError(Exception e) {
+    this.statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+    this.message = new StatusMessage(statusCode, true, e);
+  }
+
+  public void setNoQueryResults() {
+    this.statusCode = HttpServletResponse.SC_NOT_FOUND;
+    this.message = new StatusMessage(statusCode, true, "no query results");
+  }
+
+  public void setConflict(Object message) {
+    this.statusCode = HttpServletResponse.SC_CONFLICT;
+    this.message = new StatusMessage(statusCode, true, message);
+  }
+
+  public void setNotFound(Object message) {
+    this.statusCode = HttpServletResponse.SC_NOT_FOUND;
+    this.message = new StatusMessage(statusCode, true, message);
+  }
+
+  public void setBadRequest(Object message) {
+    this.statusCode = HttpServletResponse.SC_BAD_REQUEST;
+    this.message = new StatusMessage(statusCode, true, message);
+  }
+
+  public void setNotFound() {
+    setNotFound("Unable to find requested URI");
+  }
+
+  public void setMethodNotImplemented() {
+    this.statusCode = HttpServletResponse.SC_METHOD_NOT_ALLOWED;
+    this.message = new StatusMessage(statusCode, true, "method not implemented");
+  }
+
+  public void setInvalidURI() {
+    setInvalidURI("Invalid URI");
+  }
+
+  public void setInvalidURI(Object message) {
+    this.statusCode = HttpServletResponse.SC_BAD_REQUEST;
+    this.message = new StatusMessage(statusCode, true, message);
+  }
+  
+  public void setUnsupportedMediaType(Object message) {
+    this.statusCode = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
+    this.message = new StatusMessage(statusCode, true, message);
+  }
+  
+  public void setGone() {
+    this.statusCode = HttpServletResponse.SC_GONE;
+    this.message = new StatusMessage(statusCode, true, "item no longer available");
+  }
+  
+
+  // Utility
+  public void respond() throws HBaseRestException {
+    response.setStatus(this.statusCode);
+    this.serializer.writeOutput(this.message);
+  }
+
+}

Added: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java?rev=736503&view=auto
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java (added)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableController.java Wed Jan 21 16:21:16 2009
@@ -0,0 +1,170 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * 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.hadoop.hbase.rest;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.rest.exception.HBaseRestException;
+import org.apache.hadoop.hbase.rest.parser.IHBaseRestParser;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TableController extends AbstractController {
+
+  @SuppressWarnings("unused")
+  private Log LOG = LogFactory.getLog(TableController.class);
+
+  protected TableModel getModel() {
+    return (TableModel) model;
+  }
+
+  @Override
+  protected AbstractModel generateModel(
+      @SuppressWarnings("hiding") HBaseConfiguration conf, HBaseAdmin admin) {
+    return new TableModel(conf, admin);
+  }
+
+  @Override
+  public void get(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap) throws HBaseRestException {
+    TableModel innerModel = getModel();
+
+    byte[] tableName;
+
+    tableName = pathSegments[0];
+    if (pathSegments.length < 2) {
+      s.setOK(innerModel.getTableMetadata(Bytes.toString(tableName)));
+    } else {
+      if (Bytes.toString(pathSegments[1]).toLowerCase().equals(REGIONS)) {
+        s.setOK(innerModel.getTableRegions(Bytes.toString(tableName)));
+      } else {
+        s.setBadRequest("unknown query.");
+      }
+    }
+    s.respond();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @param input column descriptor JSON. Should be of the form: <pre>
+   * {"column_families":[ { "name":STRING, "bloomfilter":BOOLEAN,
+   * "max_versions":INTEGER, "compression_type":STRING, "in_memory":BOOLEAN,
+   * "block_cache_enabled":BOOLEAN, "max_value_length":INTEGER,
+   * "time_to_live":INTEGER ]} </pre> If any of the json object fields (except
+   * name) are not included the default values will be included instead. The
+   * default values are: <pre> bloomfilter => false max_versions => 3
+   * compression_type => NONE in_memory => false block_cache_enabled => false
+   * max_value_length => 2147483647 time_to_live => Integer.MAX_VALUE </pre>
+   * 
+   * @see
+   * org.apache.hadoop.hbase.rest.AbstractController#post(org.apache.hadoop.
+   * hbase.rest.Status, byte[][], java.util.Map, byte[],
+   * org.apache.hadoop.hbase.rest.parser.IHBaseRestParser)
+   */
+  @Override
+  public void post(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+      throws HBaseRestException {
+    TableModel innerModel = getModel();
+
+    byte[] tableName;
+
+    if (pathSegments.length == 0) {
+      // If no input, we don't know columnfamily schema, so send
+      // no data
+      if (input.length == 0) {
+        s.setBadRequest("no data send with post request");
+      } else {
+        HTableDescriptor htd = parser.getTableDescriptor(input);
+        // Send to innerModel. If iM returns false, means the
+        // table already exists so return conflict.
+        if (!innerModel.post(htd.getName(), htd)) {
+          s.setConflict("table already exists");
+        } else {
+          // Otherwise successfully created table. Return "created":true
+          s.setCreated();
+        }
+      }
+    } else if (Bytes.toString(pathSegments[1]).toLowerCase().equals(
+        RESTConstants.ENABLE)) {
+      tableName = pathSegments[0];
+      innerModel.enableTable(tableName);
+      s.setAccepted();
+    } else if (Bytes.toString(pathSegments[1]).toLowerCase().equals(
+        RESTConstants.DISABLE)) {
+      tableName = pathSegments[0];
+      innerModel.disableTable(tableName);
+      s.setAccepted();
+    } else {
+      s.setBadRequest("Unknown Query.");
+    }
+    s.respond();
+  }
+
+  @Override
+  public void put(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap, byte[] input, IHBaseRestParser parser)
+      throws HBaseRestException {
+    if (pathSegments.length != 1) {
+      s.setBadRequest("must specifify the name of the table");
+      s.respond();
+    } else if (queryMap.size() > 0) {
+      s
+          .setBadRequest("no query string should be specified when updating a table");
+      s.respond();
+    } else {
+      ArrayList<HColumnDescriptor> newColumns = parser
+          .getColumnDescriptors(input);
+      byte[] tableName = pathSegments[0];
+      getModel().updateTable(Bytes.toString(tableName), newColumns);
+      s.setOK();
+      s.respond();
+    }
+  }
+
+  @Override
+  public void delete(Status s, byte[][] pathSegments,
+      Map<String, String[]> queryMap) throws HBaseRestException {
+    TableModel innerModel = getModel();
+
+    byte[] tableName;
+
+    tableName = pathSegments[0];
+
+    if (pathSegments.length == 1) {
+      if (!innerModel.delete(tableName)) {
+        s.setBadRequest("table does not exist");
+      } else {
+        s.setAccepted();
+      }
+      s.respond();
+    } else {
+
+    }
+  }
+
+}
\ No newline at end of file

Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java?rev=736503&r1=736502&r2=736503&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/rest/TableHandler.java Wed Jan 21 16:21:16 2009
@@ -1,416 +0,0 @@
-/**
- * Copyright 2007 The Apache Software Foundation
- *
- * 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.hadoop.hbase.rest;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.HColumnDescriptor.CompressionType;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.znerd.xmlenc.XMLOutputter;
-
-
-/**
- * TableHandler fields all requests that deal with an individual table.
- * That means all requests that start with /api/[table_name]/... go to 
- * this handler.
- */
-public class TableHandler extends GenericHandler {
-  public static final String DISABLE = "disable";
-  public static final String ENABLE = "enable";
-  
-  public TableHandler(HBaseConfiguration conf, HBaseAdmin admin) 
-  throws ServletException{
-    super(conf, admin);
-  }
-  
-  public void doGet(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    // if it's just table name, return the metadata
-    if (pathSegments.length == 1) {
-      getTableMetadata(request, response, pathSegments[0]);
-    }
-    else{
-      HTable table = getTable(pathSegments[0]);
-      if (pathSegments[1].toLowerCase().equals(REGIONS)) {
-        // get a region list
-        getTableRegions(table, request, response);
-      }
-      else{
-        doNotFound(response, "Not handled in TableHandler");
-      }
-    }
-  }
-  
-  public void doPost(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    if (pathSegments.length == 0 || pathSegments[0].length() <= 0) {
-      // if it's a creation operation
-      putTable(request, response, pathSegments);
-    } else {
-      // if it's a disable operation or enable operation
-      String tableName = pathSegments[0];      
-      if (pathSegments[1].toLowerCase().equals(DISABLE)) {
-        admin.disableTable(tableName);
-      } else if (pathSegments[1].toLowerCase().equals(ENABLE)) {
-        admin.enableTable(tableName);
-      }
-      response.setStatus(202);
-    }
-  }
-
-  public void doPut(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    updateTable(request, response, pathSegments);
-  }
-  
-  public void doDelete(HttpServletRequest request, HttpServletResponse response, 
-    String[] pathSegments)
-  throws ServletException, IOException {
-    deleteTable(request, response, pathSegments);
-  }
-
-  /*
-   * Return region offsets.
-   * @param request
-   * @param response
-   */
-  private void getTableRegions(HTable table, final HttpServletRequest request,
-    final HttpServletResponse response)
-  throws IOException {
-    // Presumption is that this.table has already been focused on target table.
-    byte [][] startKeys = table.getStartKeys();
-    // Presumption is that this.table has already been set against target table
-    switch (ContentType.getContentType(request.getHeader(ACCEPT))) {
-      case XML:
-        setResponseHeader(response, startKeys.length > 0? 200: 204,
-            ContentType.XML.toString());
-          XMLOutputter outputter = getXMLOutputter(response.getWriter());
-          outputter.startTag("regions");
-          for (int i = 0; i < startKeys.length; i++) {
-            doElement(outputter, "region", Bytes.toString(startKeys[i]));
-          }
-          outputter.endTag();
-          outputter.endDocument();
-          outputter.getWriter().close();
-        break;
-      case PLAIN:
-        setResponseHeader(response, startKeys.length > 0? 200: 204,
-            ContentType.PLAIN.toString());
-          PrintWriter out = response.getWriter();
-          for (int i = 0; i < startKeys.length; i++) {
-            // TODO: Add in the server location.  Is it needed?
-            out.print(Bytes.toString(startKeys[i]));
-          }
-          out.close();
-        break;
-      case MIME:
-      default:
-        doNotAcceptable(response, "Unsupported Accept Header Content: " +
-          request.getHeader(CONTENT_TYPE));
-    }
-  }
-  /*
-   * Get table metadata.
-   * @param request
-   * @param response
-   * @param tableName
-   * @throws IOException
-   */
-  private void getTableMetadata(final HttpServletRequest request,
-      final HttpServletResponse response, final String tableName)
-  throws IOException {
-    HTableDescriptor [] tables = this.admin.listTables();
-    HTableDescriptor descriptor = null;
-    for (int i = 0; i < tables.length; i++) {
-      if (Bytes.toString(tables[i].getName()).equals(tableName)) {
-        descriptor = tables[i];
-        break;
-      }
-    }
-    if (descriptor == null) {
-      doNotFound(response, "Table not found!");
-    } else {
-      // Presumption is that this.table has already been set against target table
-      ContentType type = ContentType.getContentType(request.getHeader(ACCEPT));
-      switch (type) {
-      case XML:
-        setResponseHeader(response, 200, ContentType.XML.toString());
-        XMLOutputter outputter = getXMLOutputter(response.getWriter());
-        outputter.startTag("table");
-        doElement(outputter, "name", Bytes.toString(descriptor.getName()));
-        outputter.startTag("columnfamilies");
-        for (HColumnDescriptor e: descriptor.getFamilies()) {
-          outputter.startTag("columnfamily");
-          doElement(outputter, "name", Bytes.toString(e.getName()));
-          doElement(outputter, "compression", e.getCompression().toString());
-          doElement(outputter, "bloomfilter",
-              Boolean.toString(e.isBloomfilter()));
-          doElement(outputter, "max-versions",
-            Integer.toString(e.getMaxVersions()));
-          doElement(outputter, "maximum-cell-size",
-              Integer.toString(e.getMaxValueLength()));
-          outputter.endTag();
-        }
-        outputter.endTag();
-        outputter.endTag();
-        outputter.endDocument();
-        outputter.getWriter().close();
-        break;
-      case PLAIN:
-        setResponseHeader(response, 200, ContentType.PLAIN.toString());
-        PrintWriter out = response.getWriter();
-        out.print(descriptor.toString());
-        out.close();
-        break;
-      case MIME:
-      default:
-        doNotAcceptable(response, "Unsupported Accept Header Content: " +
-          request.getHeader(CONTENT_TYPE));
-      }
-    }
-  }
-  
-  private void putTable(HttpServletRequest request,
-    HttpServletResponse response, String[] pathSegments) 
-  throws IOException, ServletException {
-    switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
-      case XML:
-        putTableXml(request, response, pathSegments);
-        break;
-      case MIME:
-        doNotAcceptable(response, "Don't support multipart/related yet...");
-        break;
-      default:
-        doNotAcceptable(response, "Unsupported Accept Header Content: " +
-            request.getHeader(CONTENT_TYPE));
-    }
-  } 
-  
-  private void updateTable(HttpServletRequest request,
-    HttpServletResponse response, String[] pathSegments) 
-  throws IOException, ServletException {
-    switch(ContentType.getContentType(request.getHeader(CONTENT_TYPE))) {
-      case XML:
-        updateTableXml(request, response, pathSegments);
-        break;
-      case MIME:
-        doNotAcceptable(response, "Don't support multipart/related yet...");
-        break;
-      default:
-        doNotAcceptable(response, "Unsupported Accept Header Content: " +
-            request.getHeader(CONTENT_TYPE));
-    }
-  }
-  
-  private void deleteTable(HttpServletRequest request,
-      HttpServletResponse response, String[] pathSegments)
-  throws ServletException {
-    try {
-      String tableName = pathSegments[0];
-      String[] column_params = request.getParameterValues(COLUMN);
-      if (column_params != null && column_params.length > 0) {
-        for (String column : column_params) {
-          admin.deleteColumn(tableName, makeColumnName(column));
-        }
-      } else {
-        admin.deleteTable(tableName);
-      }
-      response.setStatus(202);
-    } catch (Exception e) {
-      throw new ServletException(e);
-    }
-  }  
-  
-  private void putTableXml(HttpServletRequest 
-    request, HttpServletResponse response, String[] pathSegments)
-  throws IOException, ServletException {
-    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
-        .newInstance();
-    // ignore all comments inside the xml file
-    docBuilderFactory.setIgnoringComments(true);
-
-    DocumentBuilder builder = null;
-    Document doc = null;
-
-    try {
-      builder = docBuilderFactory.newDocumentBuilder();
-      doc = builder.parse(request.getInputStream());
-    } catch (javax.xml.parsers.ParserConfigurationException e) {
-      throw new ServletException(e);
-    } catch (org.xml.sax.SAXException e) {
-      throw new ServletException(e);
-    }
-    
-    try {
-      Node name_node = doc.getElementsByTagName("name").item(0);
-      String table_name = name_node.getFirstChild().getNodeValue();
-      
-      HTableDescriptor htd = new HTableDescriptor(table_name);
-      NodeList columnfamily_nodes = doc.getElementsByTagName("columnfamily");
-      for (int i = 0; i < columnfamily_nodes.getLength(); i++) {
-        Element columnfamily = (Element)columnfamily_nodes.item(i);
-        htd.addFamily(putColumnFamilyXml(columnfamily));
-      }
-      admin.createTable(htd);      
-    } catch (Exception e) {
-      throw new ServletException(e);
-    }
-  }
-
-  private void updateTableXml(HttpServletRequest request,
-      HttpServletResponse response, String[] pathSegments) throws IOException,
-      ServletException {
-    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
-        .newInstance();
-    // ignore all comments inside the xml file
-    docBuilderFactory.setIgnoringComments(true);
-
-    DocumentBuilder builder = null;
-    Document doc = null;
-
-    try {
-      builder = docBuilderFactory.newDocumentBuilder();
-      doc = builder.parse(request.getInputStream());
-    } catch (javax.xml.parsers.ParserConfigurationException e) {
-      throw new ServletException(e);
-    } catch (org.xml.sax.SAXException e) {
-      throw new ServletException(e);
-    }
-
-    try {
-      String tableName = pathSegments[0];
-      HTableDescriptor htd = admin.getTableDescriptor(tableName);
-      
-      NodeList columnfamily_nodes = doc.getElementsByTagName("columnfamily");
-
-      for (int i = 0; i < columnfamily_nodes.getLength(); i++) {
-        Element columnfamily = (Element) columnfamily_nodes.item(i);
-        HColumnDescriptor hcd = putColumnFamilyXml(columnfamily, htd);
-        if (htd.hasFamily(Bytes.toBytes(hcd.getNameAsString()))) {
-          admin.modifyColumn(tableName, hcd.getNameAsString(), hcd);
-        } else {
-          admin.addColumn(tableName, hcd);
-        }
-      }
-    } catch (Exception e) {
-      throw new ServletException(e);
-    }
-  }
-  
-  private HColumnDescriptor putColumnFamilyXml(Element columnfamily) {
-    return putColumnFamilyXml(columnfamily, null);
-  }
-  
-  private HColumnDescriptor putColumnFamilyXml(Element columnfamily, HTableDescriptor currentTDesp) {
-    Node name_node = columnfamily.getElementsByTagName("name").item(0);
-    String colname = makeColumnName(name_node.getFirstChild().getNodeValue());
-    
-    int max_versions = HColumnDescriptor.DEFAULT_VERSIONS;
-    CompressionType compression = HColumnDescriptor.DEFAULT_COMPRESSION;
-    boolean in_memory = HColumnDescriptor.DEFAULT_IN_MEMORY;
-    boolean block_cache = HColumnDescriptor.DEFAULT_BLOCKCACHE;
-    int max_cell_size = HColumnDescriptor.DEFAULT_LENGTH;
-    int ttl = HColumnDescriptor.DEFAULT_TTL;
-    boolean bloomfilter = HColumnDescriptor.DEFAULT_BLOOMFILTER;
-    
-    if (currentTDesp != null) {
-      HColumnDescriptor currentCDesp = currentTDesp.getFamily(Bytes.toBytes(colname));
-      if (currentCDesp != null) {
-        max_versions = currentCDesp.getMaxVersions();
-        compression = currentCDesp.getCompression();
-        in_memory = currentCDesp.isInMemory();
-        block_cache = currentCDesp.isBlockCacheEnabled();
-        max_cell_size = currentCDesp.getMaxValueLength();
-        ttl = currentCDesp.getTimeToLive();
-        bloomfilter = currentCDesp.isBloomfilter();
-      }
-    }
-    
-    NodeList max_versions_list = columnfamily.getElementsByTagName("max-versions");
-    if (max_versions_list.getLength() > 0) {
-      max_versions = Integer.parseInt(max_versions_list.item(0).getFirstChild().getNodeValue());
-    }
-
-    NodeList compression_list = columnfamily.getElementsByTagName("compression");
-    if (compression_list.getLength() > 0) {
-      compression = CompressionType.valueOf(compression_list.item(0).getFirstChild().getNodeValue());
-    }
-
-    NodeList in_memory_list = columnfamily.getElementsByTagName("in-memory");
-    if (in_memory_list.getLength() > 0) {
-      in_memory = Boolean.valueOf(in_memory_list.item(0).getFirstChild().getNodeValue());
-    }
-    
-    NodeList block_cache_list = columnfamily.getElementsByTagName("block-cache");
-    if (block_cache_list.getLength() > 0) {
-      block_cache = Boolean.valueOf(block_cache_list.item(0).getFirstChild().getNodeValue());
-    }
-
-    NodeList max_cell_size_list = columnfamily.getElementsByTagName("max-cell-size");
-    if (max_cell_size_list.getLength() > 0) {
-      max_cell_size = Integer.valueOf(max_cell_size_list.item(0).getFirstChild().getNodeValue());
-    }
-
-    NodeList ttl_list = columnfamily.getElementsByTagName("time-to-live");
-    if (ttl_list.getLength() > 0) {
-      ttl = Integer.valueOf(ttl_list.item(0).getFirstChild().getNodeValue());
-    }
-
-    NodeList bloomfilter_list = columnfamily.getElementsByTagName("bloomfilter");
-    if (bloomfilter_list.getLength() > 0) {
-      bloomfilter = Boolean.valueOf(bloomfilter_list.item(0).getFirstChild().getNodeValue());
-    }
-    
-    HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes(colname), max_versions,
-        compression, in_memory, block_cache, max_cell_size, ttl, bloomfilter);
-    
-    NodeList metadataList = columnfamily.getElementsByTagName("metadata");
-    for (int i = 0; i < metadataList.getLength(); i++) {
-      Element metadataColumn = (Element)metadataList.item(i);
-      // extract the name and value children
-      Node mname_node = metadataColumn.getElementsByTagName("name").item(0);
-      String mname = mname_node.getFirstChild().getNodeValue();
-      Node mvalue_node = metadataColumn.getElementsByTagName("value").item(0);
-      String mvalue = mvalue_node.getFirstChild().getNodeValue();
-      hcd.setValue(mname, mvalue);
-    }
-    
-    return hcd;
-  }
-}