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 java.io.ByteArrayInputStream;
023import java.io.IOException;
024import java.io.StringWriter;
025import java.util.*;
026
027import javax.ws.rs.core.MediaType;
028import javax.xml.bind.JAXBContext;
029import javax.xml.bind.JAXBException;
030import javax.xml.bind.Marshaller;
031import javax.xml.bind.Unmarshaller;
032
033import com.fasterxml.jackson.databind.ObjectMapper;
034import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
035import org.apache.hadoop.conf.Configuration;
036import org.apache.hadoop.hbase.HBaseTestingUtility;
037import org.apache.hadoop.hbase.HColumnDescriptor;
038import org.apache.hadoop.hbase.HTableDescriptor;
039import org.apache.hadoop.hbase.TableName;
040import org.apache.hadoop.hbase.client.Admin;
041import org.apache.hadoop.hbase.rest.client.Client;
042import org.apache.hadoop.hbase.rest.client.Cluster;
043import org.apache.hadoop.hbase.rest.client.Response;
044import org.apache.hadoop.hbase.rest.model.CellModel;
045import org.apache.hadoop.hbase.rest.model.CellSetModel;
046import org.apache.hadoop.hbase.rest.model.RowModel;
047import org.apache.hadoop.hbase.util.Bytes;
048import org.junit.After;
049import org.junit.AfterClass;
050import org.junit.Before;
051import org.junit.BeforeClass;
052
053public class RowResourceBase {
054
055  protected static final String TABLE = "TestRowResource";
056
057  protected static final TableName TABLE_NAME = TableName.valueOf(TABLE);
058
059  protected static final String CFA = "a";
060  protected static final String CFB = "b";
061  protected static final String COLUMN_1 = CFA + ":1";
062  protected static final String COLUMN_2 = CFB + ":2";
063  protected static final String COLUMN_3 = CFA + ":";
064  protected static final String ROW_1 = "testrow1";
065  protected static final String VALUE_1 = "testvalue1";
066  protected static final String ROW_2 = "testrow2";
067  protected static final String VALUE_2 = "testvalue2";
068  protected static final String ROW_3 = "testrow3";
069  protected static final String VALUE_3 = "testvalue3";
070  protected static final String ROW_4 = "testrow4";
071  protected static final String VALUE_4 = "testvalue4";
072  protected static final String VALUE_5 = "5";
073  protected static final String VALUE_6 = "6";
074
075  protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
076  protected static final HBaseRESTTestingUtility REST_TEST_UTIL =
077    new HBaseRESTTestingUtility();
078  protected static Client client;
079  protected static JAXBContext context;
080  protected static Marshaller xmlMarshaller;
081  protected static Unmarshaller xmlUnmarshaller;
082  protected static Configuration conf;
083  protected static ObjectMapper jsonMapper;
084
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,
181                                      long value) 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,
264      String row, String column, 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()), Bytes.toBytes(entry.getValue())));
273      }
274    }
275
276    // This Cell need to be added as last cell.
277    rowModel.addCell(new CellModel(Bytes.toBytes(column),
278      Bytes.toBytes(valueToCheck)));
279
280    CellSetModel cellSetModel = new CellSetModel();
281    cellSetModel.addRow(rowModel);
282    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
283      cellSetModel.createProtobufOutput());
284    Thread.yield();
285    return response;
286  }
287
288  protected static Response checkAndPutValuePB(String table, String row,
289      String column, String valueToCheck, String valueToPut) throws IOException {
290    return checkAndPutValuePB(table,row,column,valueToCheck,valueToPut,null);
291  }
292    protected static Response checkAndPutValuePB(String table, String row,
293      String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException {
294    StringBuilder path = new StringBuilder();
295    path.append('/');
296    path.append(table);
297    path.append('/');
298    path.append(row);
299    path.append("?check=put");
300    return checkAndPutValuePB(path.toString(), table, row, column,
301      valueToCheck, valueToPut, otherCells);
302  }
303
304  protected static Response checkAndPutValueXML(String url, String table,
305      String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
306        throws IOException, JAXBException {
307    RowModel rowModel = new RowModel(row);
308    rowModel.addCell(new CellModel(Bytes.toBytes(column),
309      Bytes.toBytes(valueToPut)));
310
311    if(otherCells != null) {
312      for (Map.Entry<String,String> entry :otherCells.entrySet()) {
313        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
314      }
315    }
316
317    // This Cell need to be added as last cell.
318    rowModel.addCell(new CellModel(Bytes.toBytes(column),
319      Bytes.toBytes(valueToCheck)));
320    CellSetModel cellSetModel = new CellSetModel();
321    cellSetModel.addRow(rowModel);
322    StringWriter writer = new StringWriter();
323    xmlMarshaller.marshal(cellSetModel, writer);
324    Response response = client.put(url, Constants.MIMETYPE_XML,
325      Bytes.toBytes(writer.toString()));
326    Thread.yield();
327    return response;
328  }
329
330  protected static Response checkAndPutValueXML(String table, String row,
331                                                String column, String valueToCheck, String valueToPut)
332          throws IOException, JAXBException {
333    return checkAndPutValueXML(table,row,column,valueToCheck,valueToPut, null);
334  }
335
336  protected static Response checkAndPutValueXML(String table, String row,
337      String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
338        throws IOException, JAXBException {
339    StringBuilder path = new StringBuilder();
340    path.append('/');
341    path.append(table);
342    path.append('/');
343    path.append(row);
344    path.append("?check=put");
345    return checkAndPutValueXML(path.toString(), table, row, column,
346      valueToCheck, valueToPut, otherCells);
347  }
348
349  protected static Response checkAndDeleteXML(String url, String table,
350      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
351        throws IOException, JAXBException {
352    RowModel rowModel = new RowModel(row);
353
354    if(cellsToDelete != null) {
355      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
356        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
357      }
358    }
359    // Add this at the end
360    rowModel.addCell(new CellModel(Bytes.toBytes(column),
361      Bytes.toBytes(valueToCheck)));
362    CellSetModel cellSetModel = new CellSetModel();
363    cellSetModel.addRow(rowModel);
364    StringWriter writer = new StringWriter();
365    xmlMarshaller.marshal(cellSetModel, writer);
366    Response response = client.put(url, Constants.MIMETYPE_XML,
367      Bytes.toBytes(writer.toString()));
368    Thread.yield();
369    return response;
370  }
371
372  protected static Response checkAndDeleteXML(String table, String row,
373      String column, String valueToCheck) throws IOException, JAXBException {
374    return checkAndDeleteXML(table, row, column, valueToCheck, null);
375  }
376  protected static Response checkAndDeleteXML(String table, String row,
377      String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
378    StringBuilder path = new StringBuilder();
379    path.append('/');
380    path.append(table);
381    path.append('/');
382    path.append(row);
383    path.append("?check=delete");
384    return checkAndDeleteXML(path.toString(), table, row, column, valueToCheck, cellsToDelete);
385  }
386
387  protected static Response checkAndDeleteJson(String table, String row,
388      String column, String valueToCheck) throws IOException, JAXBException {
389    return checkAndDeleteJson(table, row, column, valueToCheck, null);
390  }
391
392  protected static Response checkAndDeleteJson(String table, String row,
393      String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
394    StringBuilder path = new StringBuilder();
395    path.append('/');
396    path.append(table);
397    path.append('/');
398    path.append(row);
399    path.append("?check=delete");
400    return checkAndDeleteJson(path.toString(), table, row, column, valueToCheck, cellsToDelete);
401  }
402
403  protected static Response checkAndDeleteJson(String url, String table,
404      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
405        throws IOException, JAXBException {
406    RowModel rowModel = new RowModel(row);
407
408    if(cellsToDelete != null) {
409      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
410        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
411      }
412    }
413    // Add this at the end
414    rowModel.addCell(new CellModel(Bytes.toBytes(column),
415      Bytes.toBytes(valueToCheck)));
416    CellSetModel cellSetModel = new CellSetModel();
417    cellSetModel.addRow(rowModel);
418    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
419    Response response = client.put(url, Constants.MIMETYPE_JSON,
420      Bytes.toBytes(jsonString));
421    Thread.yield();
422    return response;
423  }
424
425  protected static Response checkAndDeletePB(String table, String row,
426      String column, String value) throws IOException {
427
428    return checkAndDeletePB(table, row, column, value, null);
429  }
430
431  protected static Response checkAndDeletePB(String table, String row,
432      String column, String value, HashMap<String,String> cellsToDelete) throws IOException {
433    StringBuilder path = new StringBuilder();
434    path.append('/');
435    path.append(table);
436    path.append('/');
437    path.append(row);
438    path.append("?check=delete");
439    return checkAndDeleteValuePB(path.toString(), table, row, column, value, cellsToDelete);
440  }
441  protected static Response checkAndDeleteValuePB(String url, String table,
442      String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
443      throws IOException {
444    RowModel rowModel = new RowModel(row);
445
446    if(cellsToDelete != null) {
447      for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
448        rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
449      }
450    }
451    // Add this at the end
452    rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes
453        .toBytes(valueToCheck)));
454    CellSetModel cellSetModel = new CellSetModel();
455    cellSetModel.addRow(rowModel);
456    Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
457        cellSetModel.createProtobufOutput());
458    Thread.yield();
459    return response;
460  }
461
462  protected static Response getValueXML(String table, String startRow,
463      String endRow, String column) throws IOException {
464    StringBuilder path = new StringBuilder();
465    path.append('/');
466    path.append(table);
467    path.append('/');
468    path.append(startRow);
469    path.append(",");
470    path.append(endRow);
471    path.append('/');
472    path.append(column);
473    return getValueXML(path.toString());
474  }
475
476  protected static Response getValueXML(String url) throws IOException {
477    Response response = client.get(url, Constants.MIMETYPE_XML);
478    return response;
479  }
480
481  protected static Response getValueJson(String url) throws IOException {
482    Response response = client.get(url, Constants.MIMETYPE_JSON);
483    return response;
484  }
485
486  protected static Response deleteValue(String table, String row, String column)
487      throws IOException {
488    StringBuilder path = new StringBuilder();
489    path.append('/');
490    path.append(table);
491    path.append('/');
492    path.append(row);
493    path.append('/');
494    path.append(column);
495    Response response = client.delete(path.toString());
496    Thread.yield();
497    return response;
498  }
499
500  protected static Response getValueXML(String table, String row, String column)
501      throws IOException {
502    StringBuilder path = new StringBuilder();
503    path.append('/');
504    path.append(table);
505    path.append('/');
506    path.append(row);
507    path.append('/');
508    path.append(column);
509    return getValueXML(path.toString());
510  }
511
512  protected static Response deleteRow(String table, String row)
513      throws IOException {
514    StringBuilder path = new StringBuilder();
515    path.append('/');
516    path.append(table);
517    path.append('/');
518    path.append(row);
519    Response response = client.delete(path.toString());
520    Thread.yield();
521    return response;
522  }
523
524  protected static Response getValueJson(String table, String row,
525      String column) throws IOException {
526    StringBuilder path = new StringBuilder();
527    path.append('/');
528    path.append(table);
529    path.append('/');
530    path.append(row);
531    path.append('/');
532    path.append(column);
533    return getValueJson(path.toString());
534  }
535
536  protected static void checkValueJSON(String table, String row, String column,
537      String value) throws IOException, JAXBException {
538    Response response = getValueJson(table, row, column);
539    assertEquals(200, response.getCode());
540    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
541    ObjectMapper mapper = new JacksonJaxbJsonProvider()
542    .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
543    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
544    RowModel rowModel = cellSet.getRows().get(0);
545    CellModel cell = rowModel.getCells().get(0);
546    assertEquals(Bytes.toString(cell.getColumn()), column);
547    assertEquals(Bytes.toString(cell.getValue()), value);
548  }
549
550  protected static void checkIncrementValueJSON(String table, String row, String column,
551      long value) throws IOException, JAXBException {
552    Response response = getValueJson(table, row, column);
553    assertEquals(200, response.getCode());
554    assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
555    ObjectMapper mapper = new JacksonJaxbJsonProvider()
556            .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
557    CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
558    RowModel rowModel = cellSet.getRows().get(0);
559    CellModel cell = rowModel.getCells().get(0);
560    assertEquals(Bytes.toString(cell.getColumn()), column);
561    assertEquals(Bytes.toLong(cell.getValue()), value);
562  }
563
564  protected static Response putValueJson(String table, String row, String column,
565      String value) throws IOException, JAXBException {
566    StringBuilder path = new StringBuilder();
567    path.append('/');
568    path.append(table);
569    path.append('/');
570    path.append(row);
571    path.append('/');
572    path.append(column);
573    return putValueJson(path.toString(), table, row, column, value);
574  }
575
576  protected static Response putValueJson(String url, String table, String row, String column,
577      String value) throws IOException, JAXBException {
578    RowModel rowModel = new RowModel(row);
579    rowModel.addCell(new CellModel(Bytes.toBytes(column),
580      Bytes.toBytes(value)));
581    CellSetModel cellSetModel = new CellSetModel();
582    cellSetModel.addRow(rowModel);
583    String jsonString = jsonMapper.writeValueAsString(cellSetModel);
584    Response response = client.put(url, Constants.MIMETYPE_JSON,
585      Bytes.toBytes(jsonString));
586    Thread.yield();
587    return response;
588  }
589
590  protected static Response appendValueXML(String table, String row, String column,
591      String value) throws IOException, JAXBException {
592    StringBuilder path = new StringBuilder();
593    path.append('/');
594    path.append(table);
595    path.append('/');
596    path.append(row);
597    path.append("?check=append");
598    return putValueXML(path.toString(), table, row, column, value);
599  }
600
601  protected static Response appendValuePB(String table, String row, String column,
602      String value) throws IOException, JAXBException {
603    StringBuilder path = new StringBuilder();
604    path.append('/');
605    path.append(table);
606    path.append('/');
607    path.append(row);
608    path.append("?check=append");
609    return putValuePB(path.toString(), table, row, column, value);
610  }
611
612  protected static Response appendValueJson(String table, String row, String column,
613      String value) throws IOException, JAXBException {
614    StringBuilder path = new StringBuilder();
615    path.append('/');
616    path.append(table);
617    path.append('/');
618    path.append(row);
619    path.append("?check=append");
620    return putValueJson(path.toString(), table, row, column, value);
621  }
622
623  protected static Response incrementValueXML(String table, String row, String column,
624      String value) throws IOException, JAXBException {
625    StringBuilder path = new StringBuilder();
626    path.append('/');
627    path.append(table);
628    path.append('/');
629    path.append(row);
630    path.append("?check=increment");
631    return putValueXML(path.toString(), table, row, column, value);
632  }
633
634  protected static Response incrementValuePB(String table, String row, String column,
635      String value) throws IOException, JAXBException {
636    StringBuilder path = new StringBuilder();
637    path.append('/');
638    path.append(table);
639    path.append('/');
640    path.append(row);
641    path.append("?check=increment");
642    return putValuePB(path.toString(), table, row, column, value);
643  }
644
645  protected static Response incrementValueJson(String table, String row, String column,
646      String value) throws IOException, JAXBException {
647    StringBuilder path = new StringBuilder();
648    path.append('/');
649    path.append(table);
650    path.append('/');
651    path.append(row);
652    path.append("?check=increment");
653    return putValueJson(path.toString(), table, row, column, value);
654  }
655}