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