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