1   /*
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.rest;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.io.StringWriter;
26  
27  import javax.xml.bind.JAXBContext;
28  import javax.xml.bind.JAXBException;
29  
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.hbase.HBaseTestingUtility;
32  import org.apache.hadoop.hbase.client.HBaseAdmin;
33  import org.apache.hadoop.hbase.rest.client.Client;
34  import org.apache.hadoop.hbase.rest.client.Cluster;
35  import org.apache.hadoop.hbase.rest.client.Response;
36  import org.apache.hadoop.hbase.rest.model.ColumnSchemaModel;
37  import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
38  import org.apache.hadoop.hbase.rest.model.TestTableSchemaModel;
39  import org.apache.hadoop.hbase.util.Bytes;
40  
41  import static org.junit.Assert.*;
42  import org.junit.AfterClass;
43  import org.junit.BeforeClass;
44  import org.junit.Test;
45  
46  public class TestSchemaResource {
47    private static String TABLE1 = "TestSchemaResource1";
48    private static String TABLE2 = "TestSchemaResource2";
49  
50    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
51    private static final HBaseRESTTestingUtility REST_TEST_UTIL =
52      new HBaseRESTTestingUtility();
53    private static Client client;
54    private static JAXBContext context;
55    private static Configuration conf;
56  
57    @BeforeClass
58    public static void setUpBeforeClass() throws Exception {
59      conf = TEST_UTIL.getConfiguration();
60      TEST_UTIL.startMiniCluster(3);
61      REST_TEST_UTIL.startServletContainer(conf);
62      client = new Client(new Cluster().add("localhost",
63        REST_TEST_UTIL.getServletPort()));
64      context = JAXBContext.newInstance(
65        ColumnSchemaModel.class,
66        TableSchemaModel.class);
67    }
68  
69    @AfterClass
70    public static void tearDownAfterClass() throws Exception {
71      REST_TEST_UTIL.shutdownServletContainer();
72      TEST_UTIL.shutdownMiniCluster();
73    }
74  
75    private static byte[] toXML(TableSchemaModel model) throws JAXBException {
76      StringWriter writer = new StringWriter();
77      context.createMarshaller().marshal(model, writer);
78      return Bytes.toBytes(writer.toString());
79    }
80  
81    private static TableSchemaModel fromXML(byte[] content)
82        throws JAXBException {
83      return (TableSchemaModel) context.createUnmarshaller()
84        .unmarshal(new ByteArrayInputStream(content));
85    }
86  
87    @Test
88    public void testTableCreateAndDeleteXML() throws IOException, JAXBException {
89      String schemaPath = "/" + TABLE1 + "/schema";
90      TableSchemaModel model;
91      Response response;
92  
93      HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
94      assertFalse(admin.tableExists(TABLE1));
95  
96      // create the table
97      model = TestTableSchemaModel.buildTestModel(TABLE1);
98      TestTableSchemaModel.checkModel(model, TABLE1);
99      response = client.put(schemaPath, Constants.MIMETYPE_XML, toXML(model));
100     assertEquals(response.getCode(), 201);
101 
102     // recall the same put operation but in read-only mode
103     conf.set("hbase.rest.readonly", "true");
104     response = client.put(schemaPath, Constants.MIMETYPE_XML, toXML(model));
105     assertEquals(response.getCode(), 403);
106 
107     // make sure HBase concurs, and wait for the table to come online
108     admin.enableTable(TABLE1);
109 
110     // retrieve the schema and validate it
111     response = client.get(schemaPath, Constants.MIMETYPE_XML);
112     assertEquals(response.getCode(), 200);
113     model = fromXML(response.getBody());
114     TestTableSchemaModel.checkModel(model, TABLE1);
115 
116     // delete the table
117     client.delete(schemaPath);
118 
119     // make sure HBase concurs
120     assertFalse(admin.tableExists(TABLE1));
121 
122     // return read-only setting back to default
123     conf.set("hbase.rest.readonly", "false");
124   }
125 
126   @Test
127   public void testTableCreateAndDeletePB() throws IOException, JAXBException {
128     String schemaPath = "/" + TABLE2 + "/schema";
129     TableSchemaModel model;
130     Response response;
131 
132     HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
133     assertFalse(admin.tableExists(TABLE2));
134 
135     // create the table
136     model = TestTableSchemaModel.buildTestModel(TABLE2);
137     TestTableSchemaModel.checkModel(model, TABLE2);
138     response = client.put(schemaPath, Constants.MIMETYPE_PROTOBUF,
139       model.createProtobufOutput());
140     assertEquals(response.getCode(), 201);
141 
142     // recall the same put operation but in read-only mode
143     conf.set("hbase.rest.readonly", "true");
144     response = client.put(schemaPath, Constants.MIMETYPE_PROTOBUF,
145       model.createProtobufOutput());
146     assertEquals(response.getCode(), 403);
147 
148     // make sure HBase concurs, and wait for the table to come online
149     admin.enableTable(TABLE2);
150 
151     // retrieve the schema and validate it
152     response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
153     assertEquals(response.getCode(), 200);
154     model = new TableSchemaModel();
155     model.getObjectFromMessage(response.getBody());
156     TestTableSchemaModel.checkModel(model, TABLE2);
157 
158     // delete the table
159     client.delete(schemaPath);
160 
161     // make sure HBase concurs
162     assertFalse(admin.tableExists(TABLE2));
163 
164     // return read-only setting back to default
165     conf.set("hbase.rest.readonly", "false");
166   }
167 }