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 */ 018 019package org.apache.hadoop.fs.http.server; 020 021import com.google.common.base.Charsets; 022import org.apache.hadoop.classification.InterfaceAudience; 023import org.apache.hadoop.conf.Configuration; 024import org.apache.hadoop.fs.FileSystem; 025import org.apache.hadoop.fs.XAttrCodec; 026import org.apache.hadoop.fs.XAttrSetFlag; 027import org.apache.hadoop.fs.http.client.HttpFSFileSystem; 028import org.apache.hadoop.fs.http.client.HttpFSUtils; 029import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.AccessTimeParam; 030import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.AclPermissionParam; 031import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.BlockSizeParam; 032import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.DataParam; 033import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.DestinationParam; 034import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.FilterParam; 035import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.GroupParam; 036import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.LenParam; 037import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.ModifiedTimeParam; 038import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OffsetParam; 039import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OperationParam; 040import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OverwriteParam; 041import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OwnerParam; 042import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.PermissionParam; 043import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.RecursiveParam; 044import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.ReplicationParam; 045import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.SourcesParam; 046import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrEncodingParam; 047import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrNameParam; 048import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrSetFlagParam; 049import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrValueParam; 050import org.apache.hadoop.lib.service.FileSystemAccess; 051import org.apache.hadoop.lib.service.FileSystemAccessException; 052import org.apache.hadoop.lib.service.Groups; 053import org.apache.hadoop.lib.service.Instrumentation; 054import org.apache.hadoop.lib.servlet.FileSystemReleaseFilter; 055import org.apache.hadoop.lib.wsrs.InputStreamEntity; 056import org.apache.hadoop.lib.wsrs.Parameters; 057import org.apache.hadoop.security.UserGroupInformation; 058import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation; 059import org.json.simple.JSONObject; 060import org.slf4j.Logger; 061import org.slf4j.LoggerFactory; 062import org.slf4j.MDC; 063 064import javax.ws.rs.Consumes; 065import javax.ws.rs.DELETE; 066import javax.ws.rs.GET; 067import javax.ws.rs.POST; 068import javax.ws.rs.PUT; 069import javax.ws.rs.Path; 070import javax.ws.rs.PathParam; 071import javax.ws.rs.Produces; 072import javax.ws.rs.QueryParam; 073import javax.ws.rs.core.Context; 074import javax.ws.rs.core.MediaType; 075import javax.ws.rs.core.Response; 076import javax.ws.rs.core.UriBuilder; 077import javax.ws.rs.core.UriInfo; 078import java.io.IOException; 079import java.io.InputStream; 080import java.net.URI; 081import java.security.AccessControlException; 082import java.security.PrivilegedExceptionAction; 083import java.text.MessageFormat; 084import java.util.EnumSet; 085import java.util.List; 086import java.util.Map; 087 088/** 089 * Main class of HttpFSServer server. 090 * <p/> 091 * The <code>HttpFSServer</code> class uses Jersey JAX-RS to binds HTTP requests to the 092 * different operations. 093 */ 094@Path(HttpFSFileSystem.SERVICE_VERSION) 095@InterfaceAudience.Private 096public class HttpFSServer { 097 private static Logger AUDIT_LOG = LoggerFactory.getLogger("httpfsaudit"); 098 private static final Logger LOG = LoggerFactory.getLogger(HttpFSServer.class); 099 100 /** 101 * Executes a {@link FileSystemAccess.FileSystemExecutor} using a filesystem for the effective 102 * user. 103 * 104 * @param ugi user making the request. 105 * @param executor FileSystemExecutor to execute. 106 * 107 * @return FileSystemExecutor response 108 * 109 * @throws IOException thrown if an IO error occurrs. 110 * @throws FileSystemAccessException thrown if a FileSystemAccess releated error occurred. Thrown 111 * exceptions are handled by {@link HttpFSExceptionProvider}. 112 */ 113 private <T> T fsExecute(UserGroupInformation ugi, FileSystemAccess.FileSystemExecutor<T> executor) 114 throws IOException, FileSystemAccessException { 115 FileSystemAccess fsAccess = HttpFSServerWebApp.get().get(FileSystemAccess.class); 116 Configuration conf = HttpFSServerWebApp.get().get(FileSystemAccess.class).getFileSystemConfiguration(); 117 return fsAccess.execute(ugi.getShortUserName(), conf, executor); 118 } 119 120 /** 121 * Returns a filesystem instance. The fileystem instance is wired for release at the completion of 122 * the current Servlet request via the {@link FileSystemReleaseFilter}. 123 * <p/> 124 * If a do-as user is specified, the current user must be a valid proxyuser, otherwise an 125 * <code>AccessControlException</code> will be thrown. 126 * 127 * @param ugi principal for whom the filesystem instance is. 128 * 129 * @return a filesystem for the specified user or do-as user. 130 * 131 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 132 * handled by {@link HttpFSExceptionProvider}. 133 * @throws FileSystemAccessException thrown if a FileSystemAccess releated error occurred. Thrown 134 * exceptions are handled by {@link HttpFSExceptionProvider}. 135 */ 136 private FileSystem createFileSystem(UserGroupInformation ugi) 137 throws IOException, FileSystemAccessException { 138 String hadoopUser = ugi.getShortUserName(); 139 FileSystemAccess fsAccess = HttpFSServerWebApp.get().get(FileSystemAccess.class); 140 Configuration conf = HttpFSServerWebApp.get().get(FileSystemAccess.class).getFileSystemConfiguration(); 141 FileSystem fs = fsAccess.createFileSystem(hadoopUser, conf); 142 FileSystemReleaseFilter.setFileSystem(fs); 143 return fs; 144 } 145 146 private void enforceRootPath(HttpFSFileSystem.Operation op, String path) { 147 if (!path.equals("/")) { 148 throw new UnsupportedOperationException( 149 MessageFormat.format("Operation [{0}], invalid path [{1}], must be '/'", 150 op, path)); 151 } 152 } 153 154 /** 155 * Special binding for '/' as it is not handled by the wildcard binding. 156 * 157 * @param op the HttpFS operation of the request. 158 * @param params the HttpFS parameters of the request. 159 * 160 * @return the request response. 161 * 162 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 163 * handled by {@link HttpFSExceptionProvider}. 164 * @throws FileSystemAccessException thrown if a FileSystemAccess releated 165 * error occurred. Thrown exceptions are handled by 166 * {@link HttpFSExceptionProvider}. 167 */ 168 @GET 169 @Produces(MediaType.APPLICATION_JSON) 170 public Response getRoot(@QueryParam(OperationParam.NAME) OperationParam op, 171 @Context Parameters params) 172 throws IOException, FileSystemAccessException { 173 return get("", op, params); 174 } 175 176 private String makeAbsolute(String path) { 177 return "/" + ((path != null) ? path : ""); 178 } 179 180 /** 181 * Binding to handle GET requests, supported operations are 182 * 183 * @param path the path for operation. 184 * @param op the HttpFS operation of the request. 185 * @param params the HttpFS parameters of the request. 186 * 187 * @return the request response. 188 * 189 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 190 * handled by {@link HttpFSExceptionProvider}. 191 * @throws FileSystemAccessException thrown if a FileSystemAccess releated 192 * error occurred. Thrown exceptions are handled by 193 * {@link HttpFSExceptionProvider}. 194 */ 195 @GET 196 @Path("{path:.*}") 197 @Produces({MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON}) 198 public Response get(@PathParam("path") String path, 199 @QueryParam(OperationParam.NAME) OperationParam op, 200 @Context Parameters params) 201 throws IOException, FileSystemAccessException { 202 UserGroupInformation user = HttpUserGroupInformation.get(); 203 Response response; 204 path = makeAbsolute(path); 205 MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name()); 206 switch (op.value()) { 207 case OPEN: { 208 //Invoking the command directly using an unmanaged FileSystem that is 209 // released by the FileSystemReleaseFilter 210 final FSOperations.FSOpen command = new FSOperations.FSOpen(path); 211 final FileSystem fs = createFileSystem(user); 212 InputStream is = null; 213 UserGroupInformation ugi = UserGroupInformation 214 .createProxyUser(user.getShortUserName(), 215 UserGroupInformation.getLoginUser()); 216 try { 217 is = ugi.doAs(new PrivilegedExceptionAction<InputStream>() { 218 @Override 219 public InputStream run() throws Exception { 220 return command.execute(fs); 221 } 222 }); 223 } catch (InterruptedException ie) { 224 LOG.info("Open interrupted.", ie); 225 Thread.currentThread().interrupt(); 226 } 227 Long offset = params.get(OffsetParam.NAME, OffsetParam.class); 228 Long len = params.get(LenParam.NAME, LenParam.class); 229 AUDIT_LOG.info("[{}] offset [{}] len [{}]", 230 new Object[] { path, offset, len }); 231 InputStreamEntity entity = new InputStreamEntity(is, offset, len); 232 response = 233 Response.ok(entity).type(MediaType.APPLICATION_OCTET_STREAM).build(); 234 break; 235 } 236 case GETFILESTATUS: { 237 FSOperations.FSFileStatus command = new FSOperations.FSFileStatus(path); 238 Map json = fsExecute(user, command); 239 AUDIT_LOG.info("[{}]", path); 240 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 241 break; 242 } 243 case LISTSTATUS: { 244 String filter = params.get(FilterParam.NAME, FilterParam.class); 245 FSOperations.FSListStatus command = 246 new FSOperations.FSListStatus(path, filter); 247 Map json = fsExecute(user, command); 248 AUDIT_LOG.info("[{}] filter [{}]", path, (filter != null) ? filter : "-"); 249 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 250 break; 251 } 252 case GETHOMEDIRECTORY: { 253 enforceRootPath(op.value(), path); 254 FSOperations.FSHomeDir command = new FSOperations.FSHomeDir(); 255 JSONObject json = fsExecute(user, command); 256 AUDIT_LOG.info(""); 257 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 258 break; 259 } 260 case INSTRUMENTATION: { 261 enforceRootPath(op.value(), path); 262 Groups groups = HttpFSServerWebApp.get().get(Groups.class); 263 List<String> userGroups = groups.getGroups(user.getShortUserName()); 264 if (!userGroups.contains(HttpFSServerWebApp.get().getAdminGroup())) { 265 throw new AccessControlException( 266 "User not in HttpFSServer admin group"); 267 } 268 Instrumentation instrumentation = 269 HttpFSServerWebApp.get().get(Instrumentation.class); 270 Map snapshot = instrumentation.getSnapshot(); 271 response = Response.ok(snapshot).build(); 272 break; 273 } 274 case GETCONTENTSUMMARY: { 275 FSOperations.FSContentSummary command = 276 new FSOperations.FSContentSummary(path); 277 Map json = fsExecute(user, command); 278 AUDIT_LOG.info("[{}]", path); 279 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 280 break; 281 } 282 case GETFILECHECKSUM: { 283 FSOperations.FSFileChecksum command = 284 new FSOperations.FSFileChecksum(path); 285 Map json = fsExecute(user, command); 286 AUDIT_LOG.info("[{}]", path); 287 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 288 break; 289 } 290 case GETFILEBLOCKLOCATIONS: { 291 response = Response.status(Response.Status.BAD_REQUEST).build(); 292 break; 293 } 294 case GETACLSTATUS: { 295 FSOperations.FSAclStatus command = new FSOperations.FSAclStatus(path); 296 Map json = fsExecute(user, command); 297 AUDIT_LOG.info("ACL status for [{}]", path); 298 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 299 break; 300 } 301 case GETXATTRS: { 302 List<String> xattrNames = 303 params.getValues(XAttrNameParam.NAME, XAttrNameParam.class); 304 XAttrCodec encoding = 305 params.get(XAttrEncodingParam.NAME, XAttrEncodingParam.class); 306 FSOperations.FSGetXAttrs command = 307 new FSOperations.FSGetXAttrs(path, xattrNames, encoding); 308 @SuppressWarnings("rawtypes") Map json = fsExecute(user, command); 309 AUDIT_LOG.info("XAttrs for [{}]", path); 310 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 311 break; 312 } 313 case LISTXATTRS: { 314 FSOperations.FSListXAttrs command = new FSOperations.FSListXAttrs(path); 315 @SuppressWarnings("rawtypes") Map json = fsExecute(user, command); 316 AUDIT_LOG.info("XAttr names for [{}]", path); 317 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 318 break; 319 } 320 case LISTSTATUS_BATCH: { 321 String startAfter = params.get( 322 HttpFSParametersProvider.StartAfterParam.NAME, 323 HttpFSParametersProvider.StartAfterParam.class); 324 byte[] token = HttpFSUtils.EMPTY_BYTES; 325 if (startAfter != null) { 326 token = startAfter.getBytes(Charsets.UTF_8); 327 } 328 FSOperations.FSListStatusBatch command = new FSOperations 329 .FSListStatusBatch(path, token); 330 @SuppressWarnings("rawtypes") Map json = fsExecute(user, command); 331 AUDIT_LOG.info("[{}] token [{}]", path, token); 332 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 333 break; 334 } 335 case GETTRASHROOT: { 336 FSOperations.FSTrashRoot command = new FSOperations.FSTrashRoot(path); 337 JSONObject json = fsExecute(user, command); 338 AUDIT_LOG.info("[{}]", path); 339 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 340 break; 341 } 342 default: { 343 throw new IOException( 344 MessageFormat.format("Invalid HTTP GET operation [{0}]", op.value())); 345 } 346 } 347 return response; 348 } 349 350 351 /** 352 * Binding to handle DELETE requests. 353 * 354 * @param path the path for operation. 355 * @param op the HttpFS operation of the request. 356 * @param params the HttpFS parameters of the request. 357 * 358 * @return the request response. 359 * 360 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 361 * handled by {@link HttpFSExceptionProvider}. 362 * @throws FileSystemAccessException thrown if a FileSystemAccess releated 363 * error occurred. Thrown exceptions are handled by 364 * {@link HttpFSExceptionProvider}. 365 */ 366 @DELETE 367 @Path("{path:.*}") 368 @Produces(MediaType.APPLICATION_JSON) 369 public Response delete(@PathParam("path") String path, 370 @QueryParam(OperationParam.NAME) OperationParam op, 371 @Context Parameters params) 372 throws IOException, FileSystemAccessException { 373 UserGroupInformation user = HttpUserGroupInformation.get(); 374 Response response; 375 path = makeAbsolute(path); 376 MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name()); 377 switch (op.value()) { 378 case DELETE: { 379 Boolean recursive = 380 params.get(RecursiveParam.NAME, RecursiveParam.class); 381 AUDIT_LOG.info("[{}] recursive [{}]", path, recursive); 382 FSOperations.FSDelete command = 383 new FSOperations.FSDelete(path, recursive); 384 JSONObject json = fsExecute(user, command); 385 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 386 break; 387 } 388 default: { 389 throw new IOException( 390 MessageFormat.format("Invalid HTTP DELETE operation [{0}]", 391 op.value())); 392 } 393 } 394 return response; 395 } 396 397 /** 398 * Binding to handle POST requests. 399 * 400 * @param is the inputstream for the request payload. 401 * @param uriInfo the of the request. 402 * @param path the path for operation. 403 * @param op the HttpFS operation of the request. 404 * @param params the HttpFS parameters of the request. 405 * 406 * @return the request response. 407 * 408 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 409 * handled by {@link HttpFSExceptionProvider}. 410 * @throws FileSystemAccessException thrown if a FileSystemAccess releated 411 * error occurred. Thrown exceptions are handled by 412 * {@link HttpFSExceptionProvider}. 413 */ 414 @POST 415 @Path("{path:.*}") 416 @Consumes({"*/*"}) 417 @Produces({MediaType.APPLICATION_JSON}) 418 public Response post(InputStream is, 419 @Context UriInfo uriInfo, 420 @PathParam("path") String path, 421 @QueryParam(OperationParam.NAME) OperationParam op, 422 @Context Parameters params) 423 throws IOException, FileSystemAccessException { 424 UserGroupInformation user = HttpUserGroupInformation.get(); 425 Response response; 426 path = makeAbsolute(path); 427 MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name()); 428 switch (op.value()) { 429 case APPEND: { 430 Boolean hasData = params.get(DataParam.NAME, DataParam.class); 431 if (!hasData) { 432 response = Response.temporaryRedirect( 433 createUploadRedirectionURL(uriInfo, 434 HttpFSFileSystem.Operation.APPEND)).build(); 435 } else { 436 FSOperations.FSAppend command = 437 new FSOperations.FSAppend(is, path); 438 fsExecute(user, command); 439 AUDIT_LOG.info("[{}]", path); 440 response = Response.ok().type(MediaType.APPLICATION_JSON).build(); 441 } 442 break; 443 } 444 case CONCAT: { 445 System.out.println("HTTPFS SERVER CONCAT"); 446 String sources = params.get(SourcesParam.NAME, SourcesParam.class); 447 448 FSOperations.FSConcat command = 449 new FSOperations.FSConcat(path, sources.split(",")); 450 fsExecute(user, command); 451 AUDIT_LOG.info("[{}]", path); 452 System.out.println("SENT RESPONSE"); 453 response = Response.ok().build(); 454 break; 455 } 456 default: { 457 throw new IOException( 458 MessageFormat.format("Invalid HTTP POST operation [{0}]", 459 op.value())); 460 } 461 } 462 return response; 463 } 464 465 /** 466 * Creates the URL for an upload operation (create or append). 467 * 468 * @param uriInfo uri info of the request. 469 * @param uploadOperation operation for the upload URL. 470 * 471 * @return the URI for uploading data. 472 */ 473 protected URI createUploadRedirectionURL(UriInfo uriInfo, Enum<?> uploadOperation) { 474 UriBuilder uriBuilder = uriInfo.getRequestUriBuilder(); 475 uriBuilder = uriBuilder.replaceQueryParam(OperationParam.NAME, uploadOperation). 476 queryParam(DataParam.NAME, Boolean.TRUE); 477 return uriBuilder.build(null); 478 } 479 480 481 /** 482 * Binding to handle PUT requests. 483 * 484 * @param is the inputstream for the request payload. 485 * @param uriInfo the of the request. 486 * @param path the path for operation. 487 * @param op the HttpFS operation of the request. 488 * @param params the HttpFS parameters of the request. 489 * 490 * @return the request response. 491 * 492 * @throws IOException thrown if an IO error occurred. Thrown exceptions are 493 * handled by {@link HttpFSExceptionProvider}. 494 * @throws FileSystemAccessException thrown if a FileSystemAccess releated 495 * error occurred. Thrown exceptions are handled by 496 * {@link HttpFSExceptionProvider}. 497 */ 498 @PUT 499 @Path("{path:.*}") 500 @Consumes({"*/*"}) 501 @Produces({MediaType.APPLICATION_JSON}) 502 public Response put(InputStream is, 503 @Context UriInfo uriInfo, 504 @PathParam("path") String path, 505 @QueryParam(OperationParam.NAME) OperationParam op, 506 @Context Parameters params) 507 throws IOException, FileSystemAccessException { 508 UserGroupInformation user = HttpUserGroupInformation.get(); 509 Response response; 510 path = makeAbsolute(path); 511 MDC.put(HttpFSFileSystem.OP_PARAM, op.value().name()); 512 switch (op.value()) { 513 case CREATE: { 514 Boolean hasData = params.get(DataParam.NAME, DataParam.class); 515 if (!hasData) { 516 response = Response.temporaryRedirect( 517 createUploadRedirectionURL(uriInfo, 518 HttpFSFileSystem.Operation.CREATE)).build(); 519 } else { 520 Short permission = params.get(PermissionParam.NAME, 521 PermissionParam.class); 522 Boolean override = params.get(OverwriteParam.NAME, 523 OverwriteParam.class); 524 Short replication = params.get(ReplicationParam.NAME, 525 ReplicationParam.class); 526 Long blockSize = params.get(BlockSizeParam.NAME, 527 BlockSizeParam.class); 528 FSOperations.FSCreate command = 529 new FSOperations.FSCreate(is, path, permission, override, 530 replication, blockSize); 531 fsExecute(user, command); 532 AUDIT_LOG.info( 533 "[{}] permission [{}] override [{}] replication [{}] blockSize [{}]", 534 new Object[]{path, permission, override, replication, blockSize}); 535 response = Response.status(Response.Status.CREATED).build(); 536 } 537 break; 538 } 539 case SETXATTR: { 540 String xattrName = params.get(XAttrNameParam.NAME, 541 XAttrNameParam.class); 542 String xattrValue = params.get(XAttrValueParam.NAME, 543 XAttrValueParam.class); 544 EnumSet<XAttrSetFlag> flag = params.get(XAttrSetFlagParam.NAME, 545 XAttrSetFlagParam.class); 546 547 FSOperations.FSSetXAttr command = new FSOperations.FSSetXAttr( 548 path, xattrName, xattrValue, flag); 549 fsExecute(user, command); 550 AUDIT_LOG.info("[{}] to xAttr [{}]", path, xattrName); 551 response = Response.ok().build(); 552 break; 553 } 554 case REMOVEXATTR: { 555 String xattrName = params.get(XAttrNameParam.NAME, XAttrNameParam.class); 556 FSOperations.FSRemoveXAttr command = new FSOperations.FSRemoveXAttr( 557 path, xattrName); 558 fsExecute(user, command); 559 AUDIT_LOG.info("[{}] removed xAttr [{}]", path, xattrName); 560 response = Response.ok().build(); 561 break; 562 } 563 case MKDIRS: { 564 Short permission = params.get(PermissionParam.NAME, 565 PermissionParam.class); 566 FSOperations.FSMkdirs command = 567 new FSOperations.FSMkdirs(path, permission); 568 JSONObject json = fsExecute(user, command); 569 AUDIT_LOG.info("[{}] permission [{}]", path, permission); 570 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 571 break; 572 } 573 case RENAME: { 574 String toPath = params.get(DestinationParam.NAME, DestinationParam.class); 575 FSOperations.FSRename command = 576 new FSOperations.FSRename(path, toPath); 577 JSONObject json = fsExecute(user, command); 578 AUDIT_LOG.info("[{}] to [{}]", path, toPath); 579 response = Response.ok(json).type(MediaType.APPLICATION_JSON).build(); 580 break; 581 } 582 case SETOWNER: { 583 String owner = params.get(OwnerParam.NAME, OwnerParam.class); 584 String group = params.get(GroupParam.NAME, GroupParam.class); 585 FSOperations.FSSetOwner command = 586 new FSOperations.FSSetOwner(path, owner, group); 587 fsExecute(user, command); 588 AUDIT_LOG.info("[{}] to (O/G)[{}]", path, owner + ":" + group); 589 response = Response.ok().build(); 590 break; 591 } 592 case SETPERMISSION: { 593 Short permission = params.get(PermissionParam.NAME, 594 PermissionParam.class); 595 FSOperations.FSSetPermission command = 596 new FSOperations.FSSetPermission(path, permission); 597 fsExecute(user, command); 598 AUDIT_LOG.info("[{}] to [{}]", path, permission); 599 response = Response.ok().build(); 600 break; 601 } 602 case SETREPLICATION: { 603 Short replication = params.get(ReplicationParam.NAME, 604 ReplicationParam.class); 605 FSOperations.FSSetReplication command = 606 new FSOperations.FSSetReplication(path, replication); 607 JSONObject json = fsExecute(user, command); 608 AUDIT_LOG.info("[{}] to [{}]", path, replication); 609 response = Response.ok(json).build(); 610 break; 611 } 612 case SETTIMES: { 613 Long modifiedTime = params.get(ModifiedTimeParam.NAME, 614 ModifiedTimeParam.class); 615 Long accessTime = params.get(AccessTimeParam.NAME, 616 AccessTimeParam.class); 617 FSOperations.FSSetTimes command = 618 new FSOperations.FSSetTimes(path, modifiedTime, accessTime); 619 fsExecute(user, command); 620 AUDIT_LOG.info("[{}] to (M/A)[{}]", path, 621 modifiedTime + ":" + accessTime); 622 response = Response.ok().build(); 623 break; 624 } 625 case SETACL: { 626 String aclSpec = params.get(AclPermissionParam.NAME, 627 AclPermissionParam.class); 628 FSOperations.FSSetAcl command = 629 new FSOperations.FSSetAcl(path, aclSpec); 630 fsExecute(user, command); 631 AUDIT_LOG.info("[{}] to acl [{}]", path, aclSpec); 632 response = Response.ok().build(); 633 break; 634 } 635 case REMOVEACL: { 636 FSOperations.FSRemoveAcl command = 637 new FSOperations.FSRemoveAcl(path); 638 fsExecute(user, command); 639 AUDIT_LOG.info("[{}] removed acl", path); 640 response = Response.ok().build(); 641 break; 642 } 643 case MODIFYACLENTRIES: { 644 String aclSpec = params.get(AclPermissionParam.NAME, 645 AclPermissionParam.class); 646 FSOperations.FSModifyAclEntries command = 647 new FSOperations.FSModifyAclEntries(path, aclSpec); 648 fsExecute(user, command); 649 AUDIT_LOG.info("[{}] modify acl entry with [{}]", path, aclSpec); 650 response = Response.ok().build(); 651 break; 652 } 653 case REMOVEACLENTRIES: { 654 String aclSpec = params.get(AclPermissionParam.NAME, 655 AclPermissionParam.class); 656 FSOperations.FSRemoveAclEntries command = 657 new FSOperations.FSRemoveAclEntries(path, aclSpec); 658 fsExecute(user, command); 659 AUDIT_LOG.info("[{}] remove acl entry [{}]", path, aclSpec); 660 response = Response.ok().build(); 661 break; 662 } 663 case REMOVEDEFAULTACL: { 664 FSOperations.FSRemoveDefaultAcl command = 665 new FSOperations.FSRemoveDefaultAcl(path); 666 fsExecute(user, command); 667 AUDIT_LOG.info("[{}] remove default acl", path); 668 response = Response.ok().build(); 669 break; 670 } 671 default: { 672 throw new IOException( 673 MessageFormat.format("Invalid HTTP PUT operation [{0}]", 674 op.value())); 675 } 676 } 677 return response; 678 } 679 680}