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