001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rest;
019
020import static org.junit.Assert.assertEquals;
021
022import com.fasterxml.jackson.databind.ObjectMapper;
023import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
024
025import java.io.ByteArrayInputStream;
026import java.io.IOException;
027import java.io.StringWriter;
028
029import java.util.HashMap;
030import java.util.Map;
031import javax.ws.rs.core.MediaType;
032import javax.xml.bind.JAXBContext;
033import javax.xml.bind.JAXBException;
034import javax.xml.bind.Marshaller;
035import javax.xml.bind.Unmarshaller;
036
037import org.apache.hadoop.conf.Configuration;
038import org.apache.hadoop.hbase.HBaseTestingUtility;
039import org.apache.hadoop.hbase.HColumnDescriptor;
040import org.apache.hadoop.hbase.HTableDescriptor;
041import org.apache.hadoop.hbase.TableName;
042import org.apache.hadoop.hbase.client.Admin;
043import org.apache.hadoop.hbase.rest.client.Client;
044import org.apache.hadoop.hbase.rest.client.Cluster;
045import org.apache.hadoop.hbase.rest.client.Response;
046import org.apache.hadoop.hbase.rest.model.CellModel;
047import org.apache.hadoop.hbase.rest.model.CellSetModel;
048import org.apache.hadoop.hbase.rest.model.RowModel;
049import org.apache.hadoop.hbase.util.Bytes;
050import org.junit.After;
051import org.junit.AfterClass;
052import org.junit.Before;
053import org.junit.BeforeClass;
054
055public class RowResourceBase {
056  protected static final String TABLE = "TestRowResource";
057
058  protected static final TableName TABLE_NAME = TableName.valueOf(TABLE);
059
060  protected static final String CFA = "a";
061  protected static final String CFB = "b";
062  protected static final String COLUMN_1 = CFA + ":1";
063  protected static final String COLUMN_2 = CFB + ":2";
064  protected static final String COLUMN_3 = CFA + ":";
065  protected static final String ROW_1 = "testrow1";
066  protected static final String VALUE_1 = "testvalue1";
067  protected static final String ROW_2 = "testrow2";
068  protected static final String VALUE_2 = "testvalue2";
069  protected static final String ROW_3 = "testrow3";
070  protected static final String VALUE_3 = "testvalue3";
071  protected static final String ROW_4 = "testrow4";
072  protected static final String VALUE_4 = "testvalue4";
073  protected static final String VALUE_5 = "5";
074  protected static final String VALUE_6 = "6";
075
076  protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
077  protected static final HBaseRESTTestingUtility REST_TEST_UTIL =
078    new HBaseRESTTestingUtility();
079  protected static Client client;
080  protected static JAXBContext context;
081  protected static Marshaller xmlMarshaller;
082  protected static Unmarshaller xmlUnmarshaller;
083  protected static Configuration conf;
084  protected static ObjectMapper jsonMapper;
085
086  @BeforeClass
087  public static void setUpBeforeClass() throws Exception {
088    conf = TEST_UTIL.getConfiguration();
089    TEST_UTIL.startMiniCluster(3);
090    REST_TEST_UTIL.startServletContainer(conf);
091    context = JAXBContext.newInstance(
092        CellModel.class,
093        CellSetModel.class,
094        RowModel.class);
095    xmlMarshaller = context.createMarshaller();
096    xmlUnmarshaller = context.createUnmarshaller();
097    jsonMapper = new JacksonJaxbJsonProvider()
098    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
099    client = new Client(new Cluster().add("localhost",
100      REST_TEST_UTIL.getServletPort()));
101  }
102
103  @AfterClass
104  public static void tearDownAfterClass() throws Exception {
105    REST_TEST_UTIL.shutdownServletContainer();
106    TEST_UTIL.shutdownMiniCluster();
107  }
108
109  @Before
110  public void beforeMethod() throws Exception {
111    Admin admin = TEST_UTIL.getAdmin();
112    if (admin.tableExists(TABLE_NAME)) {
113      TEST_UTIL.deleteTable(TABLE_NAME);
114    }
115    HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLE));
116    htd.addFamily(new HColumnDescriptor(CFA));
117    htd.addFamily(new HColumnDescriptor(CFB));
118    admin.createTable(htd);
119  }
120
121  @After
122  public void afterMethod() throws Exception {
123    Admin admin = TEST_UTIL.getAdmin();
124    if (admin.tableExists(TABLE_NAME)) {
125      TEST_UTIL.deleteTable(TABLE_NAME);
126    }
127  }
128
129  static Response putValuePB(String table, String row, String column,
130      String value) throws IOException {
131    StringBuilder path = new StringBuilder();
132    path.append('/');
133    path.append(table);
134    path.append('/');
135    path.append(row);
136    path.append('/');
137    path.append(column);
138    return putValuePB(path.toString(), table, row, column, value);
139  }
140
141  static Response putValuePB(String url, String table, String row,
142      String column, String value) throws IOException {
143    RowModel rowModel = new RowModel(row);
144    rowModel.addCell(new CellModel(Bytes.toBytes(column),
145      Bytes.toBytes(value)));
146    CellSetModel cellSetModel = new CellSetModel();
147    cellSetModel.addRow(rowModel);
148    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
149      cellSetModel.createProtobufOutput());
150    Thread.yield();
151    return response;
152  }
153
154  protected static void checkValueXML(String url, String table, String row,
155      String column, String value) throws IOException, JAXBException {
156    Response response = getValueXML(url);
157    assertEquals(200, response.getCode());
158    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
159    CellSetModel cellSet = (CellSetModel)
160      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
161    RowModel rowModel = cellSet.getRows().get(0);
162    CellModel cell = rowModel.getCells().get(0);
163    assertEquals(Bytes.toString(cell.getColumn()), column);
164    assertEquals(Bytes.toString(cell.getValue()), value);
165  }
166
167  protected static void checkValueXML(String table, String row, String column,
168      String value) throws IOException, JAXBException {
169    Response response = getValueXML(table, row, column);
170    assertEquals(200, response.getCode());
171    assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
172    CellSetModel cellSet = (CellSetModel)
173      xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
174    RowModel rowModel = cellSet.getRows().get(0);
175    CellModel cell = rowModel.getCells().get(0);
176    assertEquals(Bytes.toString(cell.getColumn()), column);
177    assertEquals(Bytes.toString(cell.getValue()), value);
178  }
179
180  protected static void checkIncrementValueXML(String table, String row, String column, long value)
181      throws IOException, JAXBException {
182    Response response1 = getValueXML(table, row, column);
183    assertEquals(200, response1.getCode());
184    assertEquals(Constants.MIMETYPE_XML, response1.getHeader("content-type"));
185    CellSetModel cellSet = (CellSetModel)
186            xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response1.getBody()));
187    RowModel rowModel = cellSet.getRows().get(0);
188    CellModel cell = rowModel.getCells().get(0);
189    assertEquals(Bytes.toString(cell.getColumn()), column);
190    assertEquals(Bytes.toLong(cell.getValue()), value);
191  }
192
193  protected static Response getValuePB(String url) throws IOException {
194    Response response = client.get(url, Constants.MIMETYPE_PROTOBUF); 
195    return response;
196  }
197
198  protected static Response putValueXML(String table, String row, String column,
199      String value) throws IOException, JAXBException {
200    StringBuilder path = new StringBuilder();
201    path.append('/');
202    path.append(table);
203    path.append('/');
204    path.append(row);
205    path.append('/');
206    path.append(column);
207    return putValueXML(path.toString(), table, row, column, value);
208  }
209
210  protected static Response putValueXML(String url, String table, String row,
211      String column, String value) throws IOException, JAXBException {
212    RowModel rowModel = new RowModel(row);
213    rowModel.addCell(new CellModel(Bytes.toBytes(column),
214      Bytes.toBytes(value)));
215    CellSetModel cellSetModel = new CellSetModel();
216    cellSetModel.addRow(rowModel);
217    StringWriter writer = new StringWriter();
218    xmlMarshaller.marshal(cellSetModel, writer);
219    Response response = client.put(url, Constants.MIMETYPE_XML,
220      Bytes.toBytes(writer.toString()));
221    Thread.yield();
222    return response;
223  }
224
225  protected static Response getValuePB(String table, String row, String column)
226      throws IOException {
227    StringBuilder path = new StringBuilder();
228    path.append('/');
229    path.append(table);
230    path.append('/');
231    path.append(row);
232    path.append('/');
233    path.append(column);
234    return getValuePB(path.toString());
235  }
236
237  protected static void checkValuePB(String table, String row, String column,
238      String value) throws IOException {
239    Response response = getValuePB(table, row, column);
240    assertEquals(200, response.getCode());
241    assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
242    CellSetModel cellSet = new CellSetModel();
243    cellSet.getObjectFromMessage(response.getBody());
244    RowModel rowModel = cellSet.getRows().get(0);
245    CellModel cell = rowModel.getCells().get(0);
246    assertEquals(Bytes.toString(cell.getColumn()), column);
247    assertEquals(Bytes.toString(cell.getValue()), value);
248  }
249
250  protected static void checkIncrementValuePB(String table, String row, String column,
251      long value) throws IOException {
252    Response response = getValuePB(table, row, column);
253    assertEquals(200, response.getCode());
254    assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
255    CellSetModel cellSet = new CellSetModel();
256    cellSet.getObjectFromMessage(response.getBody());
257    RowModel rowModel = cellSet.getRows().get(0);
258    CellModel cell = rowModel.getCells().get(0);
259    assertEquals(Bytes.toString(cell.getColumn()), column);
260    assertEquals(Bytes.toLong(cell.getValue()), value);
261  }
262
263  protected static Response checkAndPutValuePB(String url, String table, String row, String column,
264      String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
265      throws IOException {
266    RowModel rowModel = new RowModel(row);
267    rowModel.addCell(new CellModel(Bytes.toBytes(column),
268      Bytes.toBytes(valueToPut)));
269
270    if (otherCells != null) {
271      for (Map.Entry<String,String> entry : otherCells.entrySet()) {
272        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()),
273          Bytes.toBytes(entry.getValue())));
274      }
275    }
276
277    // This Cell need to be added as last cell.
278    rowModel.addCell(new CellModel(Bytes.toBytes(column),
279      Bytes.toBytes(valueToCheck)));
280
281    CellSetModel cellSetModel = new CellSetModel();
282    cellSetModel.addRow(rowModel);
283    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
284      cellSetModel.createProtobufOutput());
285    Thread.yield();
286    return response;
287  }
288
289  protected static Response checkAndPutValuePB(String table, String row,
290      String column, String valueToCheck, String valueToPut) throws IOException {
291    return checkAndPutValuePB(table,row,column,valueToCheck,valueToPut,null);
292  }
293
294  protected static Response checkAndPutValuePB(String table, String row, String column,
295      String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
296      throws IOException {
297    StringBuilder path = new StringBuilder();
298    path.append('/');
299    path.append(table);
300    path.append('/');
301    path.append(row);
302    path.append("?check=put");
303    return checkAndPutValuePB(path.toString(), table, row, column,
304      valueToCheck, valueToPut, otherCells);
305  }
306
307  protected static Response checkAndPutValueXML(String url, String table, String row, String column,
308      String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
309      throws IOException, JAXBException {
310    RowModel rowModel = new RowModel(row);
311    rowModel.addCell(new CellModel(Bytes.toBytes(column),
312      Bytes.toBytes(valueToPut)));
313
314    if (otherCells != null) {
315      for (Map.Entry<String,String> entry : otherCells.entrySet()) {
316        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()),
317          Bytes.toBytes(entry.getValue())));
318      }
319    }
320
321    // This Cell need to be added as last cell.
322    rowModel.addCell(new CellModel(Bytes.toBytes(column),
323      Bytes.toBytes(valueToCheck)));
324    CellSetModel cellSetModel = new CellSetModel();
325    cellSetModel.addRow(rowModel);
326    StringWriter writer = new StringWriter();
327    xmlMarshaller.marshal(cellSetModel, writer);
328    Response response = client.put(url, Constants.MIMETYPE_XML,
329      Bytes.toBytes(writer.toString()));
330    Thread.yield();
331    return response;
332  }
333
334  protected static Response checkAndPutValueXML(String table, String row, String column,
335      String valueToCheck, String valueToPut) throws IOException, JAXBException {
336    return checkAndPutValueXML(table,row,column,valueToCheck,valueToPut, null);
337  }
338
339  protected static Response checkAndPutValueXML(String table, String row,
340      String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
341        throws IOException, JAXBException {
342    StringBuilder path = new StringBuilder();
343    path.append('/');
344    path.append(table);
345    path.append('/');
346    path.append(row);
347    path.append("?check=put");
348    return checkAndPutValueXML(path.toString(), table, row, column,
349      valueToCheck, valueToPut, otherCells);
350  }
351
352  protected static Response checkAndDeleteXML(String url, String table,
353      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
354        throws IOException, JAXBException {
355    RowModel rowModel = new RowModel(row);
356
357    if (cellsToDelete != null) {
358      for (Map.Entry<String,String> entry : cellsToDelete.entrySet()) {
359        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()),
360          Bytes.toBytes(entry.getValue())));
361      }
362    }
363    // Add this at the end
364    rowModel.addCell(new CellModel(Bytes.toBytes(column),
365      Bytes.toBytes(valueToCheck)));
366    CellSetModel cellSetModel = new CellSetModel();
367    cellSetModel.addRow(rowModel);
368    StringWriter writer = new StringWriter();
369    xmlMarshaller.marshal(cellSetModel, writer);
370    Response response = client.put(url, Constants.MIMETYPE_XML,
371      Bytes.toBytes(writer.toString()));
372    Thread.yield();
373    return response;
374  }
375
376  protected static Response checkAndDeleteXML(String table, String row,
377      String column, String valueToCheck) throws IOException, JAXBException {
378    return checkAndDeleteXML(table, row, column, valueToCheck, null);
379  }
380
381  protected static Response checkAndDeleteXML(String table, String row,
382      String column, String valueToCheck, HashMap<String,String> cellsToDelete)
383      throws IOException, JAXBException {
384    StringBuilder path = new StringBuilder();
385    path.append('/');
386    path.append(table);
387    path.append('/');
388    path.append(row);
389    path.append("?check=delete");
390    return checkAndDeleteXML(path.toString(), table, row, column, valueToCheck, cellsToDelete);
391  }
392
393  protected static Response checkAndDeleteJson(String table, String row,
394      String column, String valueToCheck) throws IOException {
395    return checkAndDeleteJson(table, row, column, valueToCheck, null);
396  }
397
398  protected static Response checkAndDeleteJson(String table, String row,
399      String column, String valueToCheck, HashMap<String,String> cellsToDelete)
400      throws IOException {
401    StringBuilder path = new StringBuilder();
402    path.append('/');
403    path.append(table);
404    path.append('/');
405    path.append(row);
406    path.append("?check=delete");
407    return checkAndDeleteJson(path.toString(), table, row, column, valueToCheck, cellsToDelete);
408  }
409
410  protected static Response checkAndDeleteJson(String url, String table,
411      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
412      throws IOException {
413    RowModel rowModel = new RowModel(row);
414
415    if (cellsToDelete != null) {
416      for (Map.Entry<String,String> entry : cellsToDelete.entrySet()) {
417        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()),
418          Bytes.toBytes(entry.getValue())));
419      }
420    }
421    // Add this at the end
422    rowModel.addCell(new CellModel(Bytes.toBytes(column),
423      Bytes.toBytes(valueToCheck)));
424    CellSetModel cellSetModel = new CellSetModel();
425    cellSetModel.addRow(rowModel);
426    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
427    Response response = client.put(url, Constants.MIMETYPE_JSON,
428      Bytes.toBytes(jsonString));
429    Thread.yield();
430    return response;
431  }
432
433  protected static Response checkAndDeletePB(String table, String row, String column, String value)
434      throws IOException {
435    return checkAndDeletePB(table, row, column, value, null);
436  }
437
438  protected static Response checkAndDeletePB(String table, String row,
439      String column, String value, HashMap<String,String> cellsToDelete) throws IOException {
440    StringBuilder path = new StringBuilder();
441    path.append('/');
442    path.append(table);
443    path.append('/');
444    path.append(row);
445    path.append("?check=delete");
446    return checkAndDeleteValuePB(path.toString(), table, row, column, value, cellsToDelete);
447  }
448  protected static Response checkAndDeleteValuePB(String url, String table,
449      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
450      throws IOException {
451    RowModel rowModel = new RowModel(row);
452
453    if (cellsToDelete != null) {
454      for (Map.Entry<String,String> entry : cellsToDelete.entrySet()) {
455        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()),
456          Bytes.toBytes(entry.getValue())));
457      }
458    }
459    // Add this at the end
460    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes
461        .toBytes(valueToCheck)));
462    CellSetModel cellSetModel = new CellSetModel();
463    cellSetModel.addRow(rowModel);
464    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
465        cellSetModel.createProtobufOutput());
466    Thread.yield();
467    return response;
468  }
469
470  protected static Response getValueXML(String table, String startRow,
471      String endRow, String column) throws IOException {
472    StringBuilder path = new StringBuilder();
473    path.append('/');
474    path.append(table);
475    path.append('/');
476    path.append(startRow);
477    path.append(",");
478    path.append(endRow);
479    path.append('/');
480    path.append(column);
481    return getValueXML(path.toString());
482  }
483
484  protected static Response getValueXML(String url) throws IOException {
485    Response response = client.get(url, Constants.MIMETYPE_XML);
486    return response;
487  }
488
489  protected static Response getValueJson(String url) throws IOException {
490    Response response = client.get(url, Constants.MIMETYPE_JSON);
491    return response;
492  }
493
494  protected static Response deleteValue(String table, String row, String column)
495      throws IOException {
496    StringBuilder path = new StringBuilder();
497    path.append('/');
498    path.append(table);
499    path.append('/');
500    path.append(row);
501    path.append('/');
502    path.append(column);
503    Response response = client.delete(path.toString());
504    Thread.yield();
505    return response;
506  }
507
508  protected static Response getValueXML(String table, String row, String column)
509      throws IOException {
510    StringBuilder path = new StringBuilder();
511    path.append('/');
512    path.append(table);
513    path.append('/');
514    path.append(row);
515    path.append('/');
516    path.append(column);
517    return getValueXML(path.toString());
518  }
519
520  protected static Response deleteRow(String table, String row)
521      throws IOException {
522    StringBuilder path = new StringBuilder();
523    path.append('/');
524    path.append(table);
525    path.append('/');
526    path.append(row);
527    Response response = client.delete(path.toString());
528    Thread.yield();
529    return response;
530  }
531
532  protected static Response getValueJson(String table, String row,
533      String column) throws IOException {
534    StringBuilder path = new StringBuilder();
535    path.append('/');
536    path.append(table);
537    path.append('/');
538    path.append(row);
539    path.append('/');
540    path.append(column);
541    return getValueJson(path.toString());
542  }
543
544  protected static void checkValueJSON(String table, String row, String column,
545      String value) throws IOException {
546    Response response = getValueJson(table, row, column);
547    assertEquals(200, response.getCode());
548    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
549    ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class,
550      MediaType.APPLICATION_JSON_TYPE);
551    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
552    RowModel rowModel = cellSet.getRows().get(0);
553    CellModel cell = rowModel.getCells().get(0);
554    assertEquals(Bytes.toString(cell.getColumn()), column);
555    assertEquals(Bytes.toString(cell.getValue()), value);
556  }
557
558  protected static void checkIncrementValueJSON(String table, String row, String column,
559      long value) throws IOException {
560    Response response = getValueJson(table, row, column);
561    assertEquals(200, response.getCode());
562    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
563    ObjectMapper mapper = new JacksonJaxbJsonProvider()
564            .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
565    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
566    RowModel rowModel = cellSet.getRows().get(0);
567    CellModel cell = rowModel.getCells().get(0);
568    assertEquals(Bytes.toString(cell.getColumn()), column);
569    assertEquals(Bytes.toLong(cell.getValue()), value);
570  }
571
572  protected static Response putValueJson(String table, String row, String column,
573      String value) throws IOException {
574    StringBuilder path = new StringBuilder();
575    path.append('/');
576    path.append(table);
577    path.append('/');
578    path.append(row);
579    path.append('/');
580    path.append(column);
581    return putValueJson(path.toString(), table, row, column, value);
582  }
583
584  protected static Response putValueJson(String url, String table, String row, String column,
585      String value) throws IOException {
586    RowModel rowModel = new RowModel(row);
587    rowModel.addCell(new CellModel(Bytes.toBytes(column),
588      Bytes.toBytes(value)));
589    CellSetModel cellSetModel = new CellSetModel();
590    cellSetModel.addRow(rowModel);
591    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
592    Response response = client.put(url, Constants.MIMETYPE_JSON,
593      Bytes.toBytes(jsonString));
594    Thread.yield();
595    return response;
596  }
597
598  protected static Response appendValueXML(String table, String row, String column,
599      String value) throws IOException, JAXBException {
600    StringBuilder path = new StringBuilder();
601    path.append('/');
602    path.append(table);
603    path.append('/');
604    path.append(row);
605    path.append("?check=append");
606    return putValueXML(path.toString(), table, row, column, value);
607  }
608
609  protected static Response appendValuePB(String table, String row, String column,
610      String value) throws IOException {
611    StringBuilder path = new StringBuilder();
612    path.append('/');
613    path.append(table);
614    path.append('/');
615    path.append(row);
616    path.append("?check=append");
617    return putValuePB(path.toString(), table, row, column, value);
618  }
619
620  protected static Response appendValueJson(String table, String row, String column,
621      String value) throws IOException, JAXBException {
622    StringBuilder path = new StringBuilder();
623    path.append('/');
624    path.append(table);
625    path.append('/');
626    path.append(row);
627    path.append("?check=append");
628    return putValueJson(path.toString(), table, row, column, value);
629  }
630
631  protected static Response incrementValueXML(String table, String row, String column,
632      String value) throws IOException, JAXBException {
633    StringBuilder path = new StringBuilder();
634    path.append('/');
635    path.append(table);
636    path.append('/');
637    path.append(row);
638    path.append("?check=increment");
639    return putValueXML(path.toString(), table, row, column, value);
640  }
641
642  protected static Response incrementValuePB(String table, String row, String column,
643      String value) throws IOException {
644    StringBuilder path = new StringBuilder();
645    path.append('/');
646    path.append(table);
647    path.append('/');
648    path.append(row);
649    path.append("?check=increment");
650    return putValuePB(path.toString(), table, row, column, value);
651  }
652
653  protected static Response incrementValueJson(String table, String row, String column,
654      String value) throws IOException, JAXBException {
655    StringBuilder path = new StringBuilder();
656    path.append('/');
657    path.append(table);
658    path.append('/');
659    path.append(row);
660    path.append("?check=increment");
661    return putValueJson(path.toString(), table, row, column, value);
662  }
663}