View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.rest;
19  
20  import static org.junit.Assert.assertEquals;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.io.StringWriter;
25  import java.util.*;
26  
27  import javax.ws.rs.core.MediaType;
28  import javax.xml.bind.JAXBContext;
29  import javax.xml.bind.JAXBException;
30  import javax.xml.bind.Marshaller;
31  import javax.xml.bind.Unmarshaller;
32  
33  import org.apache.hadoop.conf.Configuration;
34  import org.apache.hadoop.hbase.HBaseTestingUtility;
35  import org.apache.hadoop.hbase.HColumnDescriptor;
36  import org.apache.hadoop.hbase.HTableDescriptor;
37  import org.apache.hadoop.hbase.TableName;
38  import org.apache.hadoop.hbase.client.Admin;
39  import org.apache.hadoop.hbase.rest.client.Client;
40  import org.apache.hadoop.hbase.rest.client.Cluster;
41  import org.apache.hadoop.hbase.rest.client.Response;
42  import org.apache.hadoop.hbase.rest.model.CellModel;
43  import org.apache.hadoop.hbase.rest.model.CellSetModel;
44  import org.apache.hadoop.hbase.rest.model.RowModel;
45  import org.apache.hadoop.hbase.rest.provider.JacksonProvider;
46  import org.apache.hadoop.hbase.util.Bytes;
47  import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
48  import org.codehaus.jackson.map.ObjectMapper;
49  import org.junit.After;
50  import org.junit.AfterClass;
51  import org.junit.Before;
52  import org.junit.BeforeClass;
53  
54  public class RowResourceBase {
55  
56    protected static final String TABLE = "TestRowResource";
57    protected static final String CFA = "a";
58    protected static final String CFB = "b";
59    protected static final String COLUMN_1 = CFA + ":1";
60    protected static final String COLUMN_2 = CFB + ":2";
61    protected static final String COLUMN_3 = CFA + ":";
62    protected static final String ROW_1 = "testrow1";
63    protected static final String VALUE_1 = "testvalue1";
64    protected static final String ROW_2 = "testrow2";
65    protected static final String VALUE_2 = "testvalue2";
66    protected static final String ROW_3 = "testrow3";
67    protected static final String VALUE_3 = "testvalue3";
68    protected static final String ROW_4 = "testrow4";
69    protected static final String VALUE_4 = "testvalue4";
70    protected static final String VALUE_5 = "5";
71    protected static final String VALUE_6 = "6";
72  
73    protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
74    protected static final HBaseRESTTestingUtility REST_TEST_UTIL =
75      new HBaseRESTTestingUtility();
76    protected static Client client;
77    protected static JAXBContext context;
78    protected static Marshaller xmlMarshaller;
79    protected static Unmarshaller xmlUnmarshaller;
80    protected static Configuration conf;
81    protected static ObjectMapper jsonMapper;
82  
83    @BeforeClass
84    public static void setUpBeforeClass() throws Exception {
85      conf = TEST_UTIL.getConfiguration();
86      TEST_UTIL.startMiniCluster(3);
87      REST_TEST_UTIL.startServletContainer(conf);
88      context = JAXBContext.newInstance(
89          CellModel.class,
90          CellSetModel.class,
91          RowModel.class);
92      xmlMarshaller = context.createMarshaller();
93      xmlUnmarshaller = context.createUnmarshaller();
94      jsonMapper = new JacksonProvider()
95      .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
96      client = new Client(new Cluster().add("localhost",
97        REST_TEST_UTIL.getServletPort()));
98    }
99  
100   @AfterClass
101   public static void tearDownAfterClass() throws Exception {
102     REST_TEST_UTIL.shutdownServletContainer();
103     TEST_UTIL.shutdownMiniCluster();
104   }
105 
106   @Before
107   public void beforeMethod() throws Exception {
108     Admin admin = TEST_UTIL.getHBaseAdmin();
109     if (admin.tableExists(TableName.valueOf(TABLE))) {
110       TEST_UTIL.deleteTable(Bytes.toBytes(TABLE));
111     }
112     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TABLE));
113     htd.addFamily(new HColumnDescriptor(CFA));
114     htd.addFamily(new HColumnDescriptor(CFB));
115     admin.createTable(htd);
116   }
117 
118   @After
119   public void afterMethod() throws Exception {
120     Admin admin = TEST_UTIL.getHBaseAdmin();
121     if (admin.tableExists(TableName.valueOf(TABLE))) {
122       TEST_UTIL.deleteTable(Bytes.toBytes(TABLE));
123     }
124   }
125 
126   static Response putValuePB(String table, String row, String column,
127       String value) throws IOException {
128     StringBuilder path = new StringBuilder();
129     path.append('/');
130     path.append(table);
131     path.append('/');
132     path.append(row);
133     path.append('/');
134     path.append(column);
135     return putValuePB(path.toString(), table, row, column, value);
136   }
137 
138   static Response putValuePB(String url, String table, String row,
139       String column, String value) throws IOException {
140     RowModel rowModel = new RowModel(row);
141     rowModel.addCell(new CellModel(Bytes.toBytes(column),
142       Bytes.toBytes(value)));
143     CellSetModel cellSetModel = new CellSetModel();
144     cellSetModel.addRow(rowModel);
145     Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
146       cellSetModel.createProtobufOutput());
147     Thread.yield();
148     return response;
149   }
150 
151   protected static void checkValueXML(String url, String table, String row,
152       String column, String value) throws IOException, JAXBException {
153     Response response = getValueXML(url);
154     assertEquals(200, response.getCode());
155     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
156     CellSetModel cellSet = (CellSetModel)
157       xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
158     RowModel rowModel = cellSet.getRows().get(0);
159     CellModel cell = rowModel.getCells().get(0);
160     assertEquals(Bytes.toString(cell.getColumn()), column);
161     assertEquals(Bytes.toString(cell.getValue()), value);
162   }
163 
164   protected static void checkValueXML(String table, String row, String column,
165       String value) throws IOException, JAXBException {
166     Response response = getValueXML(table, row, column);
167     assertEquals(200, response.getCode());
168     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
169     CellSetModel cellSet = (CellSetModel)
170       xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
171     RowModel rowModel = cellSet.getRows().get(0);
172     CellModel cell = rowModel.getCells().get(0);
173     assertEquals(Bytes.toString(cell.getColumn()), column);
174     assertEquals(Bytes.toString(cell.getValue()), value);
175   }
176 
177   protected static void checkIncrementValueXML(String table, String row, String column,
178                                       long value) throws IOException, JAXBException {
179     Response response = getValueXML(table, row, column);
180     assertEquals(200, response.getCode());
181     assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
182     CellSetModel cellSet = (CellSetModel)
183             xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
184     RowModel rowModel = cellSet.getRows().get(0);
185     CellModel cell = rowModel.getCells().get(0);
186     assertEquals(Bytes.toString(cell.getColumn()), column);
187     assertEquals(Bytes.toLong(cell.getValue()), value);
188   }
189 
190   protected static Response getValuePB(String url) throws IOException {
191     Response response = client.get(url, Constants.MIMETYPE_PROTOBUF); 
192     return response;
193   }
194 
195   protected static Response putValueXML(String table, String row, String column,
196       String value) throws IOException, JAXBException {
197     StringBuilder path = new StringBuilder();
198     path.append('/');
199     path.append(table);
200     path.append('/');
201     path.append(row);
202     path.append('/');
203     path.append(column);
204     return putValueXML(path.toString(), table, row, column, value);
205   }
206 
207   protected static Response putValueXML(String url, String table, String row,
208       String column, String value) throws IOException, JAXBException {
209     RowModel rowModel = new RowModel(row);
210     rowModel.addCell(new CellModel(Bytes.toBytes(column),
211       Bytes.toBytes(value)));
212     CellSetModel cellSetModel = new CellSetModel();
213     cellSetModel.addRow(rowModel);
214     StringWriter writer = new StringWriter();
215     xmlMarshaller.marshal(cellSetModel, writer);
216     Response response = client.put(url, Constants.MIMETYPE_XML,
217       Bytes.toBytes(writer.toString()));
218     Thread.yield();
219     return response;
220   }
221 
222   protected static Response getValuePB(String table, String row, String column)
223       throws IOException {
224     StringBuilder path = new StringBuilder();
225     path.append('/');
226     path.append(table);
227     path.append('/');
228     path.append(row);
229     path.append('/');
230     path.append(column);
231     return getValuePB(path.toString());
232   }
233 
234   protected static void checkValuePB(String table, String row, String column,
235       String value) throws IOException {
236     Response response = getValuePB(table, row, column);
237     assertEquals(200, response.getCode());
238     assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
239     CellSetModel cellSet = new CellSetModel();
240     cellSet.getObjectFromMessage(response.getBody());
241     RowModel rowModel = cellSet.getRows().get(0);
242     CellModel cell = rowModel.getCells().get(0);
243     assertEquals(Bytes.toString(cell.getColumn()), column);
244     assertEquals(Bytes.toString(cell.getValue()), value);
245   }
246 
247   protected static void checkIncrementValuePB(String table, String row, String column,
248       long value) throws IOException {
249     Response response = getValuePB(table, row, column);
250     assertEquals(200, response.getCode());
251     assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
252     CellSetModel cellSet = new CellSetModel();
253     cellSet.getObjectFromMessage(response.getBody());
254     RowModel rowModel = cellSet.getRows().get(0);
255     CellModel cell = rowModel.getCells().get(0);
256     assertEquals(Bytes.toString(cell.getColumn()), column);
257     assertEquals(Bytes.toLong(cell.getValue()), value);
258   }
259 
260   protected static Response checkAndPutValuePB(String url, String table,
261       String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
262         throws IOException {
263     RowModel rowModel = new RowModel(row);
264     rowModel.addCell(new CellModel(Bytes.toBytes(column),
265       Bytes.toBytes(valueToPut)));
266 
267     if(otherCells != null) {
268       for (Map.Entry<String,String> entry :otherCells.entrySet()) {
269         rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
270       }
271     }
272 
273     // This Cell need to be added as last cell.
274     rowModel.addCell(new CellModel(Bytes.toBytes(column),
275       Bytes.toBytes(valueToCheck)));
276 
277     CellSetModel cellSetModel = new CellSetModel();
278     cellSetModel.addRow(rowModel);
279     Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
280       cellSetModel.createProtobufOutput());
281     Thread.yield();
282     return response;
283   }
284 
285   protected static Response checkAndPutValuePB(String table, String row,
286       String column, String valueToCheck, String valueToPut) throws IOException {
287     return checkAndPutValuePB(table,row,column,valueToCheck,valueToPut,null);
288   }
289     protected static Response checkAndPutValuePB(String table, String row,
290       String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException {
291     StringBuilder path = new StringBuilder();
292     path.append('/');
293     path.append(table);
294     path.append('/');
295     path.append(row);
296     path.append("?check=put");
297     return checkAndPutValuePB(path.toString(), table, row, column,
298       valueToCheck, valueToPut, otherCells);
299   }
300 
301   protected static Response checkAndPutValueXML(String url, String table,
302       String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
303         throws IOException, JAXBException {
304     RowModel rowModel = new RowModel(row);
305     rowModel.addCell(new CellModel(Bytes.toBytes(column),
306       Bytes.toBytes(valueToPut)));
307 
308     if(otherCells != null) {
309       for (Map.Entry<String,String> entry :otherCells.entrySet()) {
310         rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
311       }
312     }
313 
314     // This Cell need to be added as last cell.
315     rowModel.addCell(new CellModel(Bytes.toBytes(column),
316       Bytes.toBytes(valueToCheck)));
317     CellSetModel cellSetModel = new CellSetModel();
318     cellSetModel.addRow(rowModel);
319     StringWriter writer = new StringWriter();
320     xmlMarshaller.marshal(cellSetModel, writer);
321     Response response = client.put(url, Constants.MIMETYPE_XML,
322       Bytes.toBytes(writer.toString()));
323     Thread.yield();
324     return response;
325   }
326 
327   protected static Response checkAndPutValueXML(String table, String row,
328                                                 String column, String valueToCheck, String valueToPut)
329           throws IOException, JAXBException {
330     return checkAndPutValueXML(table,row,column,valueToCheck,valueToPut, null);
331   }
332 
333   protected static Response checkAndPutValueXML(String table, String row,
334       String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells)
335         throws IOException, JAXBException {
336     StringBuilder path = new StringBuilder();
337     path.append('/');
338     path.append(table);
339     path.append('/');
340     path.append(row);
341     path.append("?check=put");
342     return checkAndPutValueXML(path.toString(), table, row, column,
343       valueToCheck, valueToPut, otherCells);
344   }
345 
346   protected static Response checkAndDeleteXML(String url, String table,
347       String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
348         throws IOException, JAXBException {
349     RowModel rowModel = new RowModel(row);
350 
351     if(cellsToDelete != null) {
352       for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
353         rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
354       }
355     }
356     // Add this at the end
357     rowModel.addCell(new CellModel(Bytes.toBytes(column),
358       Bytes.toBytes(valueToCheck)));
359     CellSetModel cellSetModel = new CellSetModel();
360     cellSetModel.addRow(rowModel);
361     StringWriter writer = new StringWriter();
362     xmlMarshaller.marshal(cellSetModel, writer);
363     Response response = client.put(url, Constants.MIMETYPE_XML,
364       Bytes.toBytes(writer.toString()));
365     Thread.yield();
366     return response;
367   }
368 
369   protected static Response checkAndDeleteXML(String table, String row,
370       String column, String valueToCheck) throws IOException, JAXBException {
371     return checkAndDeleteXML(table, row, column, valueToCheck, null);
372   }
373   protected static Response checkAndDeleteXML(String table, String row,
374       String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
375     StringBuilder path = new StringBuilder();
376     path.append('/');
377     path.append(table);
378     path.append('/');
379     path.append(row);
380     path.append("?check=delete");
381     return checkAndDeleteXML(path.toString(), table, row, column, valueToCheck, cellsToDelete);
382   }
383 
384   protected static Response checkAndDeleteJson(String table, String row,
385       String column, String valueToCheck) throws IOException, JAXBException {
386     return checkAndDeleteJson(table, row, column, valueToCheck, null);
387   }
388 
389   protected static Response checkAndDeleteJson(String table, String row,
390       String column, String valueToCheck, HashMap<String,String> cellsToDelete) throws IOException, JAXBException {
391     StringBuilder path = new StringBuilder();
392     path.append('/');
393     path.append(table);
394     path.append('/');
395     path.append(row);
396     path.append("?check=delete");
397     return checkAndDeleteJson(path.toString(), table, row, column, valueToCheck, cellsToDelete);
398   }
399 
400   protected static Response checkAndDeleteJson(String url, String table,
401       String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
402         throws IOException, JAXBException {
403     RowModel rowModel = new RowModel(row);
404 
405     if(cellsToDelete != null) {
406       for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
407         rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
408       }
409     }
410     // Add this at the end
411     rowModel.addCell(new CellModel(Bytes.toBytes(column),
412       Bytes.toBytes(valueToCheck)));
413     CellSetModel cellSetModel = new CellSetModel();
414     cellSetModel.addRow(rowModel);
415     String jsonString = jsonMapper.writeValueAsString(cellSetModel);
416     Response response = client.put(url, Constants.MIMETYPE_JSON,
417       Bytes.toBytes(jsonString));
418     Thread.yield();
419     return response;
420   }
421 
422   protected static Response checkAndDeletePB(String table, String row,
423       String column, String value) throws IOException {
424 
425     return checkAndDeletePB(table, row, column, value, null);
426   }
427 
428   protected static Response checkAndDeletePB(String table, String row,
429       String column, String value, HashMap<String,String> cellsToDelete) throws IOException {
430     StringBuilder path = new StringBuilder();
431     path.append('/');
432     path.append(table);
433     path.append('/');
434     path.append(row);
435     path.append("?check=delete");
436     return checkAndDeleteValuePB(path.toString(), table, row, column, value, cellsToDelete);
437   }
438   protected static Response checkAndDeleteValuePB(String url, String table,
439       String row, String column, String valueToCheck, HashMap<String,String> cellsToDelete)
440       throws IOException {
441     RowModel rowModel = new RowModel(row);
442 
443     if(cellsToDelete != null) {
444       for (Map.Entry<String,String> entry :cellsToDelete.entrySet()) {
445         rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue())));
446       }
447     }
448     // Add this at the end
449     rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes
450         .toBytes(valueToCheck)));
451     CellSetModel cellSetModel = new CellSetModel();
452     cellSetModel.addRow(rowModel);
453     Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
454         cellSetModel.createProtobufOutput());
455     Thread.yield();
456     return response;
457   }
458 
459   protected static Response getValueXML(String table, String startRow,
460       String endRow, String column) throws IOException {
461     StringBuilder path = new StringBuilder();
462     path.append('/');
463     path.append(table);
464     path.append('/');
465     path.append(startRow);
466     path.append(",");
467     path.append(endRow);
468     path.append('/');
469     path.append(column);
470     return getValueXML(path.toString());
471   }
472 
473   protected static Response getValueXML(String url) throws IOException {
474     Response response = client.get(url, Constants.MIMETYPE_XML);
475     return response;
476   }
477 
478   protected static Response getValueJson(String url) throws IOException {
479     Response response = client.get(url, Constants.MIMETYPE_JSON);
480     return response;
481   }
482 
483   protected static Response deleteValue(String table, String row, String column)
484       throws IOException {
485     StringBuilder path = new StringBuilder();
486     path.append('/');
487     path.append(table);
488     path.append('/');
489     path.append(row);
490     path.append('/');
491     path.append(column);
492     Response response = client.delete(path.toString());
493     Thread.yield();
494     return response;
495   }
496 
497   protected static Response getValueXML(String table, String row, String column)
498       throws IOException {
499     StringBuilder path = new StringBuilder();
500     path.append('/');
501     path.append(table);
502     path.append('/');
503     path.append(row);
504     path.append('/');
505     path.append(column);
506     return getValueXML(path.toString());
507   }
508 
509   protected static Response deleteRow(String table, String row)
510       throws IOException {
511     StringBuilder path = new StringBuilder();
512     path.append('/');
513     path.append(table);
514     path.append('/');
515     path.append(row);
516     Response response = client.delete(path.toString());
517     Thread.yield();
518     return response;
519   }
520 
521   protected static Response getValueJson(String table, String row,
522       String column) throws IOException {
523     StringBuilder path = new StringBuilder();
524     path.append('/');
525     path.append(table);
526     path.append('/');
527     path.append(row);
528     path.append('/');
529     path.append(column);
530     return getValueJson(path.toString());
531   }
532 
533   protected static void checkValueJSON(String table, String row, String column,
534       String value) throws IOException, JAXBException {
535     Response response = getValueJson(table, row, column);
536     assertEquals(200, response.getCode());
537     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
538     ObjectMapper mapper = new JacksonProvider()
539     .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
540     CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
541     RowModel rowModel = cellSet.getRows().get(0);
542     CellModel cell = rowModel.getCells().get(0);
543     assertEquals(Bytes.toString(cell.getColumn()), column);
544     assertEquals(Bytes.toString(cell.getValue()), value);
545   }
546 
547   protected static void checkIncrementValueJSON(String table, String row, String column,
548       long value) throws IOException, JAXBException {
549     Response response = getValueJson(table, row, column);
550     assertEquals(200, response.getCode());
551     assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
552     ObjectMapper mapper = new JacksonJaxbJsonProvider()
553             .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
554     CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class);
555     RowModel rowModel = cellSet.getRows().get(0);
556     CellModel cell = rowModel.getCells().get(0);
557     assertEquals(Bytes.toString(cell.getColumn()), column);
558     assertEquals(Bytes.toLong(cell.getValue()), value);
559   }
560 
561   protected static Response putValueJson(String table, String row, String column,
562       String value) throws IOException, JAXBException {
563     StringBuilder path = new StringBuilder();
564     path.append('/');
565     path.append(table);
566     path.append('/');
567     path.append(row);
568     path.append('/');
569     path.append(column);
570     return putValueJson(path.toString(), table, row, column, value);
571   }
572 
573   protected static Response putValueJson(String url, String table, String row, String column,
574       String value) throws IOException, JAXBException {
575     RowModel rowModel = new RowModel(row);
576     rowModel.addCell(new CellModel(Bytes.toBytes(column),
577       Bytes.toBytes(value)));
578     CellSetModel cellSetModel = new CellSetModel();
579     cellSetModel.addRow(rowModel);
580     String jsonString = jsonMapper.writeValueAsString(cellSetModel);
581     Response response = client.put(url, Constants.MIMETYPE_JSON,
582       Bytes.toBytes(jsonString));
583     Thread.yield();
584     return response;
585   }
586 
587   protected static Response appendValueXML(String table, String row, String column,
588       String value) throws IOException, JAXBException {
589     StringBuilder path = new StringBuilder();
590     path.append('/');
591     path.append(table);
592     path.append('/');
593     path.append(row);
594     path.append("?check=append");
595     return putValueXML(path.toString(), table, row, column, value);
596   }
597 
598   protected static Response appendValuePB(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 putValuePB(path.toString(), table, row, column, value);
607   }
608 
609   protected static Response appendValueJson(String table, String row, String column,
610       String value) throws IOException, JAXBException {
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 putValueJson(path.toString(), table, row, column, value);
618   }
619 
620   protected static Response incrementValueXML(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=increment");
628     return putValueXML(path.toString(), table, row, column, value);
629   }
630 
631   protected static Response incrementValuePB(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 putValuePB(path.toString(), table, row, column, value);
640   }
641 
642   protected static Response incrementValueJson(String table, String row, String column,
643       String value) throws IOException, JAXBException {
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 putValueJson(path.toString(), table, row, column, value);
651   }
652 }