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.IOException; 026import java.util.Collection; 027import javax.ws.rs.core.MediaType; 028import javax.xml.bind.JAXBContext; 029import javax.xml.bind.Marshaller; 030import javax.xml.bind.Unmarshaller; 031 032import org.apache.hadoop.conf.Configuration; 033import org.apache.hadoop.hbase.HBaseClassTestRule; 034import org.apache.hadoop.hbase.HBaseCommonTestingUtility; 035import org.apache.hadoop.hbase.HBaseTestingUtility; 036import org.apache.hadoop.hbase.HColumnDescriptor; 037import org.apache.hadoop.hbase.HTableDescriptor; 038import org.apache.hadoop.hbase.TableName; 039import org.apache.hadoop.hbase.client.Admin; 040import org.apache.hadoop.hbase.rest.client.Client; 041import org.apache.hadoop.hbase.rest.client.Cluster; 042import org.apache.hadoop.hbase.rest.client.Response; 043import org.apache.hadoop.hbase.rest.model.CellModel; 044import org.apache.hadoop.hbase.rest.model.CellSetModel; 045import org.apache.hadoop.hbase.rest.model.RowModel; 046import org.apache.hadoop.hbase.testclassification.MediumTests; 047import org.apache.hadoop.hbase.testclassification.RestTests; 048import org.apache.hadoop.hbase.util.Bytes; 049 050import org.apache.http.Header; 051import org.apache.http.message.BasicHeader; 052 053import org.junit.AfterClass; 054import org.junit.BeforeClass; 055import org.junit.ClassRule; 056import org.junit.Test; 057import org.junit.experimental.categories.Category; 058import org.junit.runner.RunWith; 059import org.junit.runners.Parameterized; 060 061@Category({RestTests.class, MediumTests.class}) 062@RunWith(Parameterized.class) 063public class TestMultiRowResource { 064 @ClassRule 065 public static final HBaseClassTestRule CLASS_RULE = 066 HBaseClassTestRule.forClass(TestMultiRowResource.class); 067 068 private static final TableName TABLE = TableName.valueOf("TestRowResource"); 069 private static final String CFA = "a"; 070 private static final String CFB = "b"; 071 private static final String COLUMN_1 = CFA + ":1"; 072 private static final String COLUMN_2 = CFB + ":2"; 073 private static final String ROW_1 = "testrow5"; 074 private static final String VALUE_1 = "testvalue5"; 075 private static final String ROW_2 = "testrow6"; 076 private static final String VALUE_2 = "testvalue6"; 077 078 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 079 private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility(); 080 081 private static Client client; 082 private static JAXBContext context; 083 private static Marshaller marshaller; 084 private static Unmarshaller unmarshaller; 085 private static Configuration conf; 086 087 private static Header extraHdr = null; 088 private static boolean csrfEnabled = true; 089 090 @Parameterized.Parameters 091 public static Collection<Object[]> data() { 092 return HBaseCommonTestingUtility.BOOLEAN_PARAMETERIZED; 093 } 094 095 public TestMultiRowResource(Boolean csrf) { 096 csrfEnabled = csrf; 097 } 098 099 @BeforeClass 100 public static void setUpBeforeClass() throws Exception { 101 conf = TEST_UTIL.getConfiguration(); 102 conf.setBoolean(RESTServer.REST_CSRF_ENABLED_KEY, csrfEnabled); 103 if (csrfEnabled) { 104 conf.set(RESTServer.REST_CSRF_BROWSER_USERAGENTS_REGEX_KEY, ".*"); 105 } 106 extraHdr = new BasicHeader(RESTServer.REST_CSRF_CUSTOM_HEADER_DEFAULT, ""); 107 TEST_UTIL.startMiniCluster(); 108 REST_TEST_UTIL.startServletContainer(conf); 109 context = JAXBContext.newInstance( 110 CellModel.class, 111 CellSetModel.class, 112 RowModel.class); 113 marshaller = context.createMarshaller(); 114 unmarshaller = context.createUnmarshaller(); 115 client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())); 116 Admin admin = TEST_UTIL.getAdmin(); 117 if (admin.tableExists(TABLE)) { 118 return; 119 } 120 HTableDescriptor htd = new HTableDescriptor(TABLE); 121 htd.addFamily(new HColumnDescriptor(CFA)); 122 htd.addFamily(new HColumnDescriptor(CFB)); 123 admin.createTable(htd); 124 } 125 126 @AfterClass 127 public static void tearDownAfterClass() throws Exception { 128 REST_TEST_UTIL.shutdownServletContainer(); 129 TEST_UTIL.shutdownMiniCluster(); 130 } 131 132 @Test 133 public void testMultiCellGetJSON() throws IOException { 134 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 135 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 136 137 StringBuilder path = new StringBuilder(); 138 path.append("/"); 139 path.append(TABLE); 140 path.append("/multiget/?row="); 141 path.append(ROW_1); 142 path.append("&row="); 143 path.append(ROW_2); 144 145 if (csrfEnabled) { 146 Response response = client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1)); 147 assertEquals(400, response.getCode()); 148 } 149 150 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 151 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 152 153 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 154 assertEquals(200, response.getCode()); 155 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); 156 157 client.delete(row_5_url, extraHdr); 158 client.delete(row_6_url, extraHdr); 159 } 160 161 @Test 162 public void testMultiCellGetXML() throws IOException { 163 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 164 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 165 166 StringBuilder path = new StringBuilder(); 167 path.append("/"); 168 path.append(TABLE); 169 path.append("/multiget/?row="); 170 path.append(ROW_1); 171 path.append("&row="); 172 path.append(ROW_2); 173 174 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 175 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 176 177 Response response = client.get(path.toString(), Constants.MIMETYPE_XML); 178 assertEquals(200, response.getCode()); 179 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type")); 180 181 client.delete(row_5_url, extraHdr); 182 client.delete(row_6_url, extraHdr); 183 } 184 185 @Test 186 public void testMultiCellGetWithColsJSON() throws IOException { 187 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 188 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 189 190 StringBuilder path = new StringBuilder(); 191 path.append("/"); 192 path.append(TABLE); 193 path.append("/multiget"); 194 path.append("/" + COLUMN_1 + "," + CFB); 195 path.append("?row="); 196 path.append(ROW_1); 197 path.append("&row="); 198 path.append(ROW_2); 199 200 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 201 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 202 203 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 204 assertEquals(200, response.getCode()); 205 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 206 MediaType.APPLICATION_JSON_TYPE); 207 CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); 208 assertEquals(2, cellSet.getRows().size()); 209 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 210 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 211 assertEquals(ROW_2, Bytes.toString(cellSet.getRows().get(1).getKey())); 212 assertEquals(VALUE_2, Bytes.toString(cellSet.getRows().get(1).getCells().get(0).getValue())); 213 214 client.delete(row_5_url, extraHdr); 215 client.delete(row_6_url, extraHdr); 216 } 217 218 @Test 219 public void testMultiCellGetJSONNotFound() throws IOException { 220 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 221 222 StringBuilder path = new StringBuilder(); 223 path.append("/"); 224 path.append(TABLE); 225 path.append("/multiget/?row="); 226 path.append(ROW_1); 227 path.append("&row="); 228 path.append(ROW_2); 229 230 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 231 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 232 assertEquals(200, response.getCode()); 233 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(CellSetModel.class, 234 MediaType.APPLICATION_JSON_TYPE); 235 CellSetModel cellSet = (CellSetModel) mapper.readValue(response.getBody(), CellSetModel.class); 236 assertEquals(1, cellSet.getRows().size()); 237 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 238 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 239 client.delete(row_5_url, extraHdr); 240 } 241 242 @Test 243 public void testMultiCellGetWithColsInQueryPathJSON() throws IOException { 244 String row_5_url = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1; 245 String row_6_url = "/" + TABLE + "/" + ROW_2 + "/" + COLUMN_2; 246 247 StringBuilder path = new StringBuilder(); 248 path.append("/"); 249 path.append(TABLE); 250 path.append("/multiget/?row="); 251 path.append(ROW_1); 252 path.append("/"); 253 path.append(COLUMN_1); 254 path.append("&row="); 255 path.append(ROW_2); 256 path.append("/"); 257 path.append(COLUMN_1); 258 259 client.post(row_5_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_1), extraHdr); 260 client.post(row_6_url, Constants.MIMETYPE_BINARY, Bytes.toBytes(VALUE_2), extraHdr); 261 262 Response response = client.get(path.toString(), Constants.MIMETYPE_JSON); 263 assertEquals(200, response.getCode()); 264 ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper( 265 CellSetModel.class, MediaType.APPLICATION_JSON_TYPE); 266 CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); 267 assertEquals(1, cellSet.getRows().size()); 268 assertEquals(ROW_1, Bytes.toString(cellSet.getRows().get(0).getKey())); 269 assertEquals(VALUE_1, Bytes.toString(cellSet.getRows().get(0).getCells().get(0).getValue())); 270 271 client.delete(row_5_url, extraHdr); 272 client.delete(row_6_url, extraHdr); 273 } 274}