Revert "HBASE-26523 Upgrade hbase-thirdparty dependency to 4.0.0 (#3910)"
[hbase.git] / hbase-rest / src / main / java / org / apache / hadoop / hbase / rest / NamespacesInstanceResource.java
blob09c8f319e0c1497619e5b8f881b283e5dfb74f34
1 /*
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org.apache.hadoop.hbase.rest;
21 import java.io.IOException;
22 import java.util.List;
23 import javax.servlet.ServletContext;
24 import javax.ws.rs.Consumes;
25 import javax.ws.rs.DELETE;
26 import javax.ws.rs.GET;
27 import javax.ws.rs.POST;
28 import javax.ws.rs.PUT;
29 import javax.ws.rs.Path;
30 import javax.ws.rs.PathParam;
31 import javax.ws.rs.Produces;
32 import javax.ws.rs.core.Context;
33 import javax.ws.rs.core.HttpHeaders;
34 import javax.ws.rs.core.Response;
35 import javax.ws.rs.core.UriInfo;
36 import org.apache.hadoop.hbase.NamespaceDescriptor;
37 import org.apache.hadoop.hbase.client.Admin;
38 import org.apache.hadoop.hbase.client.TableDescriptor;
39 import org.apache.hadoop.hbase.rest.model.NamespacesInstanceModel;
40 import org.apache.hadoop.hbase.rest.model.TableListModel;
41 import org.apache.hadoop.hbase.rest.model.TableModel;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.apache.yetus.audience.InterfaceAudience;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 /**
48 * Implements the following REST end points:
49 * <p>
50 * <tt>/namespaces/{namespace} GET: get namespace properties.</tt>
51 * <tt>/namespaces/{namespace} POST: create namespace.</tt>
52 * <tt>/namespaces/{namespace} PUT: alter namespace.</tt>
53 * <tt>/namespaces/{namespace} DELETE: drop namespace.</tt>
54 * <tt>/namespaces/{namespace}/tables GET: list namespace's tables.</tt>
55 * <p>
57 @InterfaceAudience.Private
58 public class NamespacesInstanceResource extends ResourceBase {
60 private static final Logger LOG = LoggerFactory.getLogger(NamespacesInstanceResource.class);
61 String namespace;
62 boolean queryTables = false;
64 /**
65 * Constructor for standard NamespaceInstanceResource.
66 * @throws IOException
68 public NamespacesInstanceResource(String namespace) throws IOException {
69 this(namespace, false);
72 /**
73 * Constructor for querying namespace table list via NamespaceInstanceResource.
74 * @throws IOException
76 public NamespacesInstanceResource(String namespace, boolean queryTables) throws IOException {
77 super();
78 this.namespace = namespace;
79 this.queryTables = queryTables;
82 /**
83 * Build a response for GET namespace description or GET list of namespace tables.
84 * @param context servlet context
85 * @param uriInfo (JAX-RS context variable) request URL
86 * @return A response containing NamespacesInstanceModel for a namespace descriptions and
87 * TableListModel for a list of namespace tables.
89 @GET
90 @Produces({MIMETYPE_TEXT, MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
91 MIMETYPE_PROTOBUF_IETF})
92 public Response get(final @Context ServletContext context,
93 final @Context UriInfo uriInfo) {
94 if (LOG.isTraceEnabled()) {
95 LOG.trace("GET " + uriInfo.getAbsolutePath());
97 servlet.getMetrics().incrementRequests(1);
99 // Respond to list of namespace tables requests.
100 if(queryTables){
101 TableListModel tableModel = new TableListModel();
102 try{
103 List<TableDescriptor> tables =
104 servlet.getAdmin().listTableDescriptorsByNamespace(Bytes.toBytes(namespace));
105 for (TableDescriptor table : tables) {
106 tableModel.add(new TableModel(table.getTableName().getQualifierAsString()));
109 servlet.getMetrics().incrementSucessfulGetRequests(1);
110 return Response.ok(tableModel).build();
111 }catch(IOException e) {
112 servlet.getMetrics().incrementFailedGetRequests(1);
113 throw new RuntimeException("Cannot retrieve table list for '" + namespace + "'.");
117 // Respond to namespace description requests.
118 try {
119 NamespacesInstanceModel rowModel =
120 new NamespacesInstanceModel(servlet.getAdmin(), namespace);
121 servlet.getMetrics().incrementSucessfulGetRequests(1);
122 return Response.ok(rowModel).build();
123 } catch (IOException e) {
124 servlet.getMetrics().incrementFailedGetRequests(1);
125 throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
130 * Build a response for PUT alter namespace with properties specified.
131 * @param model properties used for alter.
132 * @param uriInfo (JAX-RS context variable) request URL
133 * @return response code.
135 @PUT
136 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
137 MIMETYPE_PROTOBUF_IETF})
138 public Response put(final NamespacesInstanceModel model, final @Context UriInfo uriInfo) {
139 return processUpdate(model, true, uriInfo);
143 * Build a response for POST create namespace with properties specified.
144 * @param model properties used for create.
145 * @param uriInfo (JAX-RS context variable) request URL
146 * @return response code.
148 @POST
149 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
150 MIMETYPE_PROTOBUF_IETF})
151 public Response post(final NamespacesInstanceModel model,
152 final @Context UriInfo uriInfo) {
153 return processUpdate(model, false, uriInfo);
157 // Check that POST or PUT is valid and then update namespace.
158 private Response processUpdate(NamespacesInstanceModel model, final boolean updateExisting,
159 final UriInfo uriInfo) {
160 if (LOG.isTraceEnabled()) {
161 LOG.trace((updateExisting ? "PUT " : "POST ") + uriInfo.getAbsolutePath());
163 if (model == null) {
164 try {
165 model = new NamespacesInstanceModel(namespace);
166 } catch(IOException ioe) {
167 servlet.getMetrics().incrementFailedPutRequests(1);
168 throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
171 servlet.getMetrics().incrementRequests(1);
173 if (servlet.isReadOnly()) {
174 servlet.getMetrics().incrementFailedPutRequests(1);
175 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
176 .entity("Forbidden" + CRLF).build();
179 Admin admin = null;
180 boolean namespaceExists = false;
181 try {
182 admin = servlet.getAdmin();
183 namespaceExists = doesNamespaceExist(admin, namespace);
184 }catch (IOException e) {
185 servlet.getMetrics().incrementFailedPutRequests(1);
186 return processException(e);
189 // Do not allow creation if namespace already exists.
190 if(!updateExisting && namespaceExists){
191 servlet.getMetrics().incrementFailedPutRequests(1);
192 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT).
193 entity("Namespace '" + namespace + "' already exists. Use REST PUT " +
194 "to alter the existing namespace.").build();
197 // Do not allow altering if namespace does not exist.
198 if (updateExisting && !namespaceExists){
199 servlet.getMetrics().incrementFailedPutRequests(1);
200 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT).
201 entity("Namespace '" + namespace + "' does not exist. Use " +
202 "REST POST to create the namespace.").build();
205 return createOrUpdate(model, uriInfo, admin, updateExisting);
208 // Do the actual namespace create or alter.
209 private Response createOrUpdate(final NamespacesInstanceModel model, final UriInfo uriInfo,
210 final Admin admin, final boolean updateExisting) {
211 NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(namespace);
212 builder.addConfiguration(model.getProperties());
213 if(model.getProperties().size() > 0){
214 builder.addConfiguration(model.getProperties());
216 NamespaceDescriptor nsd = builder.build();
218 try{
219 if(updateExisting){
220 admin.modifyNamespace(nsd);
221 }else{
222 admin.createNamespace(nsd);
224 }catch (IOException e) {
225 servlet.getMetrics().incrementFailedPutRequests(1);
226 return processException(e);
229 servlet.getMetrics().incrementSucessfulPutRequests(1);
231 return updateExisting ? Response.ok(uriInfo.getAbsolutePath()).build() :
232 Response.created(uriInfo.getAbsolutePath()).build();
235 private boolean doesNamespaceExist(Admin admin, String namespaceName) throws IOException{
236 NamespaceDescriptor[] nd = admin.listNamespaceDescriptors();
237 for(int i = 0; i < nd.length; i++){
238 if(nd[i].getName().equals(namespaceName)){
239 return true;
242 return false;
246 * Build a response for DELETE delete namespace.
247 * @param message value not used.
248 * @param headers value not used.
249 * @return response code.
251 @DELETE
252 public Response deleteNoBody(final byte[] message,
253 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
254 if (LOG.isTraceEnabled()) {
255 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
257 if (servlet.isReadOnly()) {
258 servlet.getMetrics().incrementFailedDeleteRequests(1);
259 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
260 .entity("Forbidden" + CRLF).build();
263 try{
264 Admin admin = servlet.getAdmin();
265 if (!doesNamespaceExist(admin, namespace)){
266 return Response.status(Response.Status.NOT_FOUND).type(MIMETYPE_TEXT).
267 entity("Namespace '" + namespace + "' does not exists. Cannot " +
268 "drop namespace.").build();
271 admin.deleteNamespace(namespace);
272 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
273 return Response.ok().build();
275 } catch (IOException e) {
276 servlet.getMetrics().incrementFailedDeleteRequests(1);
277 return processException(e);
282 * Dispatch to NamespaceInstanceResource for getting list of tables.
284 @Path("tables")
285 public NamespacesInstanceResource getNamespaceInstanceResource(
286 final @PathParam("tables") String namespace) throws IOException {
287 return new NamespacesInstanceResource(this.namespace, true);