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