1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.rest;
20
21 import java.io.IOException;
22
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
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.hadoop.hbase.HTableDescriptor;
40 import org.apache.hadoop.hbase.NamespaceDescriptor;
41 import org.apache.hadoop.hbase.classification.InterfaceAudience;
42 import org.apache.hadoop.hbase.client.Admin;
43 import org.apache.hadoop.hbase.rest.model.NamespacesInstanceModel;
44 import org.apache.hadoop.hbase.rest.model.TableListModel;
45 import org.apache.hadoop.hbase.rest.model.TableModel;
46
47
48
49
50
51
52
53
54
55
56
57 @InterfaceAudience.Private
58 public class NamespacesInstanceResource extends ResourceBase {
59
60 private static final Log LOG = LogFactory.getLog(NamespacesInstanceResource.class);
61 String namespace;
62 boolean queryTables = false;
63
64
65
66
67
68 public NamespacesInstanceResource(String namespace) throws IOException {
69 this(namespace, false);
70 }
71
72
73
74
75
76 public NamespacesInstanceResource(String namespace, boolean queryTables) throws IOException {
77 super();
78 this.namespace = namespace;
79 this.queryTables = queryTables;
80 }
81
82
83
84
85
86
87
88
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());
96 }
97 servlet.getMetrics().incrementRequests(1);
98
99
100 if(queryTables){
101 TableListModel tableModel = new TableListModel();
102 try{
103 HTableDescriptor[] tables = servlet.getAdmin().listTableDescriptorsByNamespace(namespace);
104 for(int i = 0; i < tables.length; i++){
105 tableModel.add(new TableModel(tables[i].getTableName().getQualifierAsString()));
106 }
107
108 servlet.getMetrics().incrementSucessfulGetRequests(1);
109 return Response.ok(tableModel).build();
110 }catch(IOException e) {
111 servlet.getMetrics().incrementFailedGetRequests(1);
112 throw new RuntimeException("Cannot retrieve table list for '" + namespace + "'.");
113 }
114 }
115
116
117 try {
118 NamespacesInstanceModel rowModel =
119 new NamespacesInstanceModel(servlet.getAdmin(), namespace);
120 servlet.getMetrics().incrementSucessfulGetRequests(1);
121 return Response.ok(rowModel).build();
122 } catch (IOException e) {
123 servlet.getMetrics().incrementFailedGetRequests(1);
124 throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
125 }
126 }
127
128
129
130
131
132
133
134 @PUT
135 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
136 MIMETYPE_PROTOBUF_IETF})
137 public Response put(final NamespacesInstanceModel model, final @Context UriInfo uriInfo) {
138 if (LOG.isTraceEnabled()) {
139 LOG.trace("PUT " + uriInfo.getAbsolutePath());
140 }
141 servlet.getMetrics().incrementRequests(1);
142 return processUpdate(model, true, uriInfo);
143 }
144
145
146
147
148
149
150
151 @PUT
152 public Response putNoBody(final byte[] message,
153 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
154 if (LOG.isTraceEnabled()) {
155 LOG.trace("PUT " + uriInfo.getAbsolutePath());
156 }
157 servlet.getMetrics().incrementRequests(1);
158 try{
159 NamespacesInstanceModel model = new NamespacesInstanceModel(namespace);
160 return processUpdate(model, true, uriInfo);
161 }catch(IOException ioe){
162 servlet.getMetrics().incrementFailedPutRequests(1);
163 throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
164 }
165 }
166
167
168
169
170
171
172
173 @POST
174 @Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
175 MIMETYPE_PROTOBUF_IETF})
176 public Response post(final NamespacesInstanceModel model,
177 final @Context UriInfo uriInfo) {
178
179 if (LOG.isTraceEnabled()) {
180 LOG.trace("POST " + uriInfo.getAbsolutePath());
181 }
182 servlet.getMetrics().incrementRequests(1);
183 return processUpdate(model, false, uriInfo);
184 }
185
186
187
188
189
190
191
192 @POST
193 public Response postNoBody(final byte[] message,
194 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
195 if (LOG.isTraceEnabled()) {
196 LOG.trace("POST " + uriInfo.getAbsolutePath());
197 }
198 servlet.getMetrics().incrementRequests(1);
199 try{
200 NamespacesInstanceModel model = new NamespacesInstanceModel(namespace);
201 return processUpdate(model, false, uriInfo);
202 }catch(IOException ioe){
203 servlet.getMetrics().incrementFailedPutRequests(1);
204 throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
205 }
206 }
207
208
209 private Response processUpdate(final NamespacesInstanceModel model, final boolean updateExisting,
210 final UriInfo uriInfo) {
211 if (servlet.isReadOnly()) {
212 servlet.getMetrics().incrementFailedPutRequests(1);
213 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
214 .entity("Forbidden" + CRLF).build();
215 }
216
217 Admin admin = null;
218 boolean namespaceExists = false;
219 try {
220 admin = servlet.getAdmin();
221 namespaceExists = doesNamespaceExist(admin, namespace);
222 }catch (IOException e) {
223 servlet.getMetrics().incrementFailedPutRequests(1);
224 return processException(e);
225 }
226
227
228 if(!updateExisting && namespaceExists){
229 servlet.getMetrics().incrementFailedPutRequests(1);
230 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT).
231 entity("Namespace '" + namespace + "' already exists. Use REST PUT " +
232 "to alter the existing namespace.").build();
233 }
234
235
236 if (updateExisting && !namespaceExists){
237 servlet.getMetrics().incrementFailedPutRequests(1);
238 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT).
239 entity("Namespace '" + namespace + "' does not exist. Use " +
240 "REST POST to create the namespace.").build();
241 }
242
243 return createOrUpdate(model, uriInfo, admin, updateExisting);
244 }
245
246
247 private Response createOrUpdate(final NamespacesInstanceModel model, final UriInfo uriInfo,
248 final Admin admin, final boolean updateExisting) {
249 NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(namespace);
250 builder.addConfiguration(model.getProperties());
251 if(model.getProperties().size() > 0){
252 builder.addConfiguration(model.getProperties());
253 }
254 NamespaceDescriptor nsd = builder.build();
255
256 try{
257 if(updateExisting){
258 admin.modifyNamespace(nsd);
259 }else{
260 admin.createNamespace(nsd);
261 }
262 }catch (IOException e) {
263 servlet.getMetrics().incrementFailedPutRequests(1);
264 return processException(e);
265 }
266
267 servlet.getMetrics().incrementSucessfulPutRequests(1);
268 return Response.created(uriInfo.getAbsolutePath()).build();
269 }
270
271 private boolean doesNamespaceExist(Admin admin, String namespaceName) throws IOException{
272 NamespaceDescriptor[] nd = admin.listNamespaceDescriptors();
273 for(int i = 0; i < nd.length; i++){
274 if(nd[i].getName().equals(namespaceName)){
275 return true;
276 }
277 }
278 return false;
279 }
280
281
282
283
284
285
286
287 @DELETE
288 public Response deleteNoBody(final byte[] message,
289 final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
290 if (LOG.isTraceEnabled()) {
291 LOG.trace("DELETE " + uriInfo.getAbsolutePath());
292 }
293 if (servlet.isReadOnly()) {
294 servlet.getMetrics().incrementFailedDeleteRequests(1);
295 return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
296 .entity("Forbidden" + CRLF).build();
297 }
298
299 try{
300 Admin admin = servlet.getAdmin();
301 if (!doesNamespaceExist(admin, namespace)){
302 return Response.status(Response.Status.NOT_FOUND).type(MIMETYPE_TEXT).
303 entity("Namespace '" + namespace + "' does not exists. Cannot " +
304 "drop namespace.").build();
305 }
306
307 admin.deleteNamespace(namespace);
308 servlet.getMetrics().incrementSucessfulDeleteRequests(1);
309 return Response.ok().build();
310
311 } catch (IOException e) {
312 servlet.getMetrics().incrementFailedDeleteRequests(1);
313 return processException(e);
314 }
315 }
316
317
318
319
320 @Path("tables")
321 public NamespacesInstanceResource getNamespaceInstanceResource(
322 final @PathParam("tables") String namespace) throws IOException {
323 return new NamespacesInstanceResource(this.namespace, true);
324 }
325 }