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 */ 018package org.apache.hadoop.fs.http.server; 019 020import org.apache.hadoop.classification.InterfaceAudience; 021import org.apache.hadoop.fs.ContentSummary; 022import org.apache.hadoop.fs.FileChecksum; 023import org.apache.hadoop.fs.FileStatus; 024import org.apache.hadoop.fs.FileSystem; 025import org.apache.hadoop.fs.FilterFileSystem; 026import org.apache.hadoop.fs.GlobFilter; 027import org.apache.hadoop.fs.Path; 028import org.apache.hadoop.fs.PathFilter; 029import org.apache.hadoop.fs.XAttrCodec; 030import org.apache.hadoop.fs.XAttrSetFlag; 031import org.apache.hadoop.fs.http.client.HttpFSFileSystem; 032import org.apache.hadoop.fs.permission.AclEntry; 033import org.apache.hadoop.fs.permission.AclStatus; 034import org.apache.hadoop.fs.permission.FsPermission; 035import org.apache.hadoop.io.IOUtils; 036import org.apache.hadoop.lib.service.FileSystemAccess; 037import org.json.simple.JSONArray; 038import org.json.simple.JSONObject; 039 040import java.io.FileNotFoundException; 041import java.io.IOException; 042import java.io.InputStream; 043import java.io.OutputStream; 044import java.util.EnumSet; 045import java.util.LinkedHashMap; 046import java.util.List; 047import java.util.Map; 048import java.util.Map.Entry; 049 050/** 051 * FileSystem operation executors used by {@link HttpFSServer}. 052 */ 053@InterfaceAudience.Private 054public class FSOperations { 055 056 /** 057 * @param fileStatus a FileStatus object 058 * @return JSON map suitable for wire transport 059 */ 060 private static Map<String, Object> toJson(FileStatus fileStatus) { 061 Map<String, Object> json = new LinkedHashMap<>(); 062 json.put(HttpFSFileSystem.FILE_STATUS_JSON, toJsonInner(fileStatus, true)); 063 return json; 064 } 065 066 /** 067 * @param fileStatuses list of FileStatus objects 068 * @param isFile is the fileStatuses from a file path 069 * @return JSON map suitable for wire transport 070 */ 071 @SuppressWarnings({"unchecked"}) 072 private static Map<String, Object> toJson(FileStatus[] fileStatuses, 073 boolean isFile) { 074 Map<String, Object> json = new LinkedHashMap<>(); 075 Map<String, Object> inner = new LinkedHashMap<>(); 076 JSONArray statuses = new JSONArray(); 077 for (FileStatus f : fileStatuses) { 078 statuses.add(toJsonInner(f, isFile)); 079 } 080 inner.put(HttpFSFileSystem.FILE_STATUS_JSON, statuses); 081 json.put(HttpFSFileSystem.FILE_STATUSES_JSON, inner); 082 return json; 083 } 084 085 /** 086 * Not meant to be called directly except by the other toJson functions. 087 */ 088 private static Map<String, Object> toJsonInner(FileStatus fileStatus, 089 boolean emptyPathSuffix) { 090 Map<String, Object> json = new LinkedHashMap<String, Object>(); 091 json.put(HttpFSFileSystem.PATH_SUFFIX_JSON, 092 (emptyPathSuffix) ? "" : fileStatus.getPath().getName()); 093 json.put(HttpFSFileSystem.TYPE_JSON, 094 HttpFSFileSystem.FILE_TYPE.getType(fileStatus).toString()); 095 json.put(HttpFSFileSystem.LENGTH_JSON, fileStatus.getLen()); 096 json.put(HttpFSFileSystem.OWNER_JSON, fileStatus.getOwner()); 097 json.put(HttpFSFileSystem.GROUP_JSON, fileStatus.getGroup()); 098 json.put(HttpFSFileSystem.PERMISSION_JSON, 099 HttpFSFileSystem.permissionToString(fileStatus.getPermission())); 100 json.put(HttpFSFileSystem.ACCESS_TIME_JSON, fileStatus.getAccessTime()); 101 json.put(HttpFSFileSystem.MODIFICATION_TIME_JSON, 102 fileStatus.getModificationTime()); 103 json.put(HttpFSFileSystem.BLOCK_SIZE_JSON, fileStatus.getBlockSize()); 104 json.put(HttpFSFileSystem.REPLICATION_JSON, fileStatus.getReplication()); 105 if (fileStatus.getPermission().getAclBit()) { 106 json.put(HttpFSFileSystem.ACL_BIT_JSON, true); 107 } 108 if (fileStatus.getPermission().getEncryptedBit()) { 109 json.put(HttpFSFileSystem.ENC_BIT_JSON, true); 110 } 111 return json; 112 } 113 114 /** 115 * Serializes a DirectoryEntries object into the JSON for a 116 * WebHDFS {@link org.apache.hadoop.hdfs.protocol.DirectoryListing}. 117 * <p> 118 * These two classes are slightly different, due to the impedance 119 * mismatches between the WebHDFS and FileSystem APIs. 120 * @param entries 121 * @param isFile is the entries from a file path 122 * @return json 123 */ 124 private static Map<String, Object> toJson(FileSystem.DirectoryEntries 125 entries, boolean isFile) { 126 Map<String, Object> json = new LinkedHashMap<>(); 127 Map<String, Object> inner = new LinkedHashMap<>(); 128 Map<String, Object> fileStatuses = toJson(entries.getEntries(), isFile); 129 inner.put(HttpFSFileSystem.PARTIAL_LISTING_JSON, fileStatuses); 130 inner.put(HttpFSFileSystem.REMAINING_ENTRIES_JSON, entries.hasMore() ? 1 131 : 0); 132 json.put(HttpFSFileSystem.DIRECTORY_LISTING_JSON, inner); 133 return json; 134 } 135 136 /** Converts an <code>AclStatus</code> object into a JSON object. 137 * 138 * @param aclStatus AclStatus object 139 * 140 * @return The JSON representation of the ACLs for the file 141 */ 142 @SuppressWarnings({"unchecked"}) 143 private static Map<String,Object> aclStatusToJSON(AclStatus aclStatus) { 144 Map<String,Object> json = new LinkedHashMap<String,Object>(); 145 Map<String,Object> inner = new LinkedHashMap<String,Object>(); 146 JSONArray entriesArray = new JSONArray(); 147 inner.put(HttpFSFileSystem.OWNER_JSON, aclStatus.getOwner()); 148 inner.put(HttpFSFileSystem.GROUP_JSON, aclStatus.getGroup()); 149 inner.put(HttpFSFileSystem.ACL_STICKY_BIT_JSON, aclStatus.isStickyBit()); 150 for ( AclEntry e : aclStatus.getEntries() ) { 151 entriesArray.add(e.toString()); 152 } 153 inner.put(HttpFSFileSystem.ACL_ENTRIES_JSON, entriesArray); 154 json.put(HttpFSFileSystem.ACL_STATUS_JSON, inner); 155 return json; 156 } 157 158 /** 159 * Converts a <code>FileChecksum</code> object into a JSON array 160 * object. 161 * 162 * @param checksum file checksum. 163 * 164 * @return The JSON representation of the file checksum. 165 */ 166 @SuppressWarnings({"unchecked"}) 167 private static Map fileChecksumToJSON(FileChecksum checksum) { 168 Map json = new LinkedHashMap(); 169 json.put(HttpFSFileSystem.CHECKSUM_ALGORITHM_JSON, checksum.getAlgorithmName()); 170 json.put(HttpFSFileSystem.CHECKSUM_BYTES_JSON, 171 org.apache.hadoop.util.StringUtils.byteToHexString(checksum.getBytes())); 172 json.put(HttpFSFileSystem.CHECKSUM_LENGTH_JSON, checksum.getLength()); 173 Map response = new LinkedHashMap(); 174 response.put(HttpFSFileSystem.FILE_CHECKSUM_JSON, json); 175 return response; 176 } 177 178 /** 179 * Converts xAttrs to a JSON object. 180 * 181 * @param xAttrs file xAttrs. 182 * @param encoding format of xattr values. 183 * 184 * @return The JSON representation of the xAttrs. 185 * @throws IOException 186 */ 187 @SuppressWarnings({"unchecked", "rawtypes"}) 188 private static Map xAttrsToJSON(Map<String, byte[]> xAttrs, 189 XAttrCodec encoding) throws IOException { 190 Map jsonMap = new LinkedHashMap(); 191 JSONArray jsonArray = new JSONArray(); 192 if (xAttrs != null) { 193 for (Entry<String, byte[]> e : xAttrs.entrySet()) { 194 Map json = new LinkedHashMap(); 195 json.put(HttpFSFileSystem.XATTR_NAME_JSON, e.getKey()); 196 if (e.getValue() != null) { 197 json.put(HttpFSFileSystem.XATTR_VALUE_JSON, 198 XAttrCodec.encodeValue(e.getValue(), encoding)); 199 } 200 jsonArray.add(json); 201 } 202 } 203 jsonMap.put(HttpFSFileSystem.XATTRS_JSON, jsonArray); 204 return jsonMap; 205 } 206 207 /** 208 * Converts xAttr names to a JSON object. 209 * 210 * @param names file xAttr names. 211 * 212 * @return The JSON representation of the xAttr names. 213 * @throws IOException 214 */ 215 @SuppressWarnings({"unchecked", "rawtypes"}) 216 private static Map xAttrNamesToJSON(List<String> names) throws IOException { 217 Map jsonMap = new LinkedHashMap(); 218 jsonMap.put(HttpFSFileSystem.XATTRNAMES_JSON, JSONArray.toJSONString(names)); 219 return jsonMap; 220 } 221 222 /** 223 * Converts a <code>ContentSummary</code> object into a JSON array 224 * object. 225 * 226 * @param contentSummary the content summary 227 * 228 * @return The JSON representation of the content summary. 229 */ 230 @SuppressWarnings({"unchecked"}) 231 private static Map contentSummaryToJSON(ContentSummary contentSummary) { 232 Map json = new LinkedHashMap(); 233 json.put(HttpFSFileSystem.CONTENT_SUMMARY_DIRECTORY_COUNT_JSON, contentSummary.getDirectoryCount()); 234 json.put(HttpFSFileSystem.CONTENT_SUMMARY_FILE_COUNT_JSON, contentSummary.getFileCount()); 235 json.put(HttpFSFileSystem.CONTENT_SUMMARY_LENGTH_JSON, contentSummary.getLength()); 236 json.put(HttpFSFileSystem.CONTENT_SUMMARY_QUOTA_JSON, contentSummary.getQuota()); 237 json.put(HttpFSFileSystem.CONTENT_SUMMARY_SPACE_CONSUMED_JSON, contentSummary.getSpaceConsumed()); 238 json.put(HttpFSFileSystem.CONTENT_SUMMARY_SPACE_QUOTA_JSON, contentSummary.getSpaceQuota()); 239 Map response = new LinkedHashMap(); 240 response.put(HttpFSFileSystem.CONTENT_SUMMARY_JSON, json); 241 return response; 242 } 243 244 /** 245 * Converts an object into a Json Map with with one key-value entry. 246 * <p/> 247 * It assumes the given value is either a JSON primitive type or a 248 * <code>JsonAware</code> instance. 249 * 250 * @param name name for the key of the entry. 251 * @param value for the value of the entry. 252 * 253 * @return the JSON representation of the key-value pair. 254 */ 255 @SuppressWarnings("unchecked") 256 private static JSONObject toJSON(String name, Object value) { 257 JSONObject json = new JSONObject(); 258 json.put(name, value); 259 return json; 260 } 261 262 /** 263 * Executor that performs an append FileSystemAccess files system operation. 264 */ 265 @InterfaceAudience.Private 266 public static class FSAppend implements FileSystemAccess.FileSystemExecutor<Void> { 267 private InputStream is; 268 private Path path; 269 270 /** 271 * Creates an Append executor. 272 * 273 * @param is input stream to append. 274 * @param path path of the file to append. 275 */ 276 public FSAppend(InputStream is, String path) { 277 this.is = is; 278 this.path = new Path(path); 279 } 280 281 /** 282 * Executes the filesystem operation. 283 * 284 * @param fs filesystem instance to use. 285 * 286 * @return void. 287 * 288 * @throws IOException thrown if an IO error occured. 289 */ 290 @Override 291 public Void execute(FileSystem fs) throws IOException { 292 int bufferSize = fs.getConf().getInt("httpfs.buffer.size", 4096); 293 OutputStream os = fs.append(path, bufferSize); 294 IOUtils.copyBytes(is, os, bufferSize, true); 295 os.close(); 296 return null; 297 } 298 299 } 300 301 /** 302 * Executor that performs an append FileSystemAccess files system operation. 303 */ 304 @InterfaceAudience.Private 305 public static class FSConcat implements FileSystemAccess.FileSystemExecutor<Void> { 306 private Path path; 307 private Path[] sources; 308 309 /** 310 * Creates a Concat executor. 311 * 312 * @param path target path to concat to. 313 * @param sources comma seperated absolute paths to use as sources. 314 */ 315 public FSConcat(String path, String[] sources) { 316 this.sources = new Path[sources.length]; 317 318 for(int i = 0; i < sources.length; i++) { 319 this.sources[i] = new Path(sources[i]); 320 } 321 322 this.path = new Path(path); 323 } 324 325 /** 326 * Executes the filesystem operation. 327 * 328 * @param fs filesystem instance to use. 329 * 330 * @return void. 331 * 332 * @throws IOException thrown if an IO error occured. 333 */ 334 @Override 335 public Void execute(FileSystem fs) throws IOException { 336 fs.concat(path, sources); 337 return null; 338 } 339 340 } 341 342 /** 343 * Executor that performs a content-summary FileSystemAccess files system operation. 344 */ 345 @InterfaceAudience.Private 346 public static class FSContentSummary implements FileSystemAccess.FileSystemExecutor<Map> { 347 private Path path; 348 349 /** 350 * Creates a content-summary executor. 351 * 352 * @param path the path to retrieve the content-summary. 353 */ 354 public FSContentSummary(String path) { 355 this.path = new Path(path); 356 } 357 358 /** 359 * Executes the filesystem operation. 360 * 361 * @param fs filesystem instance to use. 362 * 363 * @return a Map object (JSON friendly) with the content-summary. 364 * 365 * @throws IOException thrown if an IO error occured. 366 */ 367 @Override 368 public Map execute(FileSystem fs) throws IOException { 369 ContentSummary contentSummary = fs.getContentSummary(path); 370 return contentSummaryToJSON(contentSummary); 371 } 372 373 } 374 375 /** 376 * Executor that performs a create FileSystemAccess files system operation. 377 */ 378 @InterfaceAudience.Private 379 public static class FSCreate implements FileSystemAccess.FileSystemExecutor<Void> { 380 private InputStream is; 381 private Path path; 382 private short permission; 383 private boolean override; 384 private short replication; 385 private long blockSize; 386 387 /** 388 * Creates a Create executor. 389 * 390 * @param is input stream to for the file to create. 391 * @param path path of the file to create. 392 * @param perm permission for the file. 393 * @param override if the file should be overriden if it already exist. 394 * @param repl the replication factor for the file. 395 * @param blockSize the block size for the file. 396 */ 397 public FSCreate(InputStream is, String path, short perm, boolean override, 398 short repl, long blockSize) { 399 this.is = is; 400 this.path = new Path(path); 401 this.permission = perm; 402 this.override = override; 403 this.replication = repl; 404 this.blockSize = blockSize; 405 } 406 407 /** 408 * Executes the filesystem operation. 409 * 410 * @param fs filesystem instance to use. 411 * 412 * @return The URI of the created file. 413 * 414 * @throws IOException thrown if an IO error occured. 415 */ 416 @Override 417 public Void execute(FileSystem fs) throws IOException { 418 if (replication == -1) { 419 replication = fs.getDefaultReplication(path); 420 } 421 if (blockSize == -1) { 422 blockSize = fs.getDefaultBlockSize(path); 423 } 424 FsPermission fsPermission = new FsPermission(permission); 425 int bufferSize = fs.getConf().getInt("httpfs.buffer.size", 4096); 426 OutputStream os = fs.create(path, fsPermission, override, bufferSize, replication, blockSize, null); 427 IOUtils.copyBytes(is, os, bufferSize, true); 428 os.close(); 429 return null; 430 } 431 432 } 433 434 /** 435 * Executor that performs a delete FileSystemAccess files system operation. 436 */ 437 @InterfaceAudience.Private 438 public static class FSDelete implements FileSystemAccess.FileSystemExecutor<JSONObject> { 439 private Path path; 440 private boolean recursive; 441 442 /** 443 * Creates a Delete executor. 444 * 445 * @param path path to delete. 446 * @param recursive if the delete should be recursive or not. 447 */ 448 public FSDelete(String path, boolean recursive) { 449 this.path = new Path(path); 450 this.recursive = recursive; 451 } 452 453 /** 454 * Executes the filesystem operation. 455 * 456 * @param fs filesystem instance to use. 457 * 458 * @return <code>true</code> if the delete operation was successful, 459 * <code>false</code> otherwise. 460 * 461 * @throws IOException thrown if an IO error occured. 462 */ 463 @Override 464 public JSONObject execute(FileSystem fs) throws IOException { 465 boolean deleted = fs.delete(path, recursive); 466 return toJSON(HttpFSFileSystem.DELETE_JSON.toLowerCase(), deleted); 467 } 468 469 } 470 471 /** 472 * Executor that performs a file-checksum FileSystemAccess files system operation. 473 */ 474 @InterfaceAudience.Private 475 public static class FSFileChecksum implements FileSystemAccess.FileSystemExecutor<Map> { 476 private Path path; 477 478 /** 479 * Creates a file-checksum executor. 480 * 481 * @param path the path to retrieve the checksum. 482 */ 483 public FSFileChecksum(String path) { 484 this.path = new Path(path); 485 } 486 487 /** 488 * Executes the filesystem operation. 489 * 490 * @param fs filesystem instance to use. 491 * 492 * @return a Map object (JSON friendly) with the file checksum. 493 * 494 * @throws IOException thrown if an IO error occured. 495 */ 496 @Override 497 public Map execute(FileSystem fs) throws IOException { 498 FileChecksum checksum = fs.getFileChecksum(path); 499 return fileChecksumToJSON(checksum); 500 } 501 502 } 503 504 /** 505 * Executor that performs a file-status FileSystemAccess files system operation. 506 */ 507 @InterfaceAudience.Private 508 public static class FSFileStatus implements FileSystemAccess.FileSystemExecutor<Map> { 509 private Path path; 510 511 /** 512 * Creates a file-status executor. 513 * 514 * @param path the path to retrieve the status. 515 */ 516 public FSFileStatus(String path) { 517 this.path = new Path(path); 518 } 519 520 /** 521 * Executes the filesystem getFileStatus operation and returns the 522 * result in a JSONish Map. 523 * 524 * @param fs filesystem instance to use. 525 * 526 * @return a Map object (JSON friendly) with the file status. 527 * 528 * @throws IOException thrown if an IO error occurred. 529 */ 530 @Override 531 public Map execute(FileSystem fs) throws IOException { 532 FileStatus status = fs.getFileStatus(path); 533 return toJson(status); 534 } 535 536 } 537 538 /** 539 * Executor that performs a home-dir FileSystemAccess files system operation. 540 */ 541 @InterfaceAudience.Private 542 public static class FSHomeDir implements FileSystemAccess.FileSystemExecutor<JSONObject> { 543 544 /** 545 * Executes the filesystem operation. 546 * 547 * @param fs filesystem instance to use. 548 * 549 * @return a JSON object with the user home directory. 550 * 551 * @throws IOException thrown if an IO error occured. 552 */ 553 @Override 554 @SuppressWarnings("unchecked") 555 public JSONObject execute(FileSystem fs) throws IOException { 556 Path homeDir = fs.getHomeDirectory(); 557 JSONObject json = new JSONObject(); 558 json.put(HttpFSFileSystem.HOME_DIR_JSON, homeDir.toUri().getPath()); 559 return json; 560 } 561 562 } 563 564 /** 565 * Executor that performs a list-status FileSystemAccess files system operation. 566 */ 567 @InterfaceAudience.Private 568 public static class FSListStatus implements FileSystemAccess.FileSystemExecutor<Map>, PathFilter { 569 private Path path; 570 private PathFilter filter; 571 572 /** 573 * Creates a list-status executor. 574 * 575 * @param path the directory to retrieve the status of its contents. 576 * @param filter glob filter to use. 577 * 578 * @throws IOException thrown if the filter expression is incorrect. 579 */ 580 public FSListStatus(String path, String filter) throws IOException { 581 this.path = new Path(path); 582 this.filter = (filter == null) ? this : new GlobFilter(filter); 583 } 584 585 /** 586 * Returns data for a JSON Map containing the information for 587 * the set of files in 'path' that match 'filter'. 588 * 589 * @param fs filesystem instance to use. 590 * 591 * @return a Map with the file status of the directory 592 * contents that match the filter 593 * 594 * @throws IOException thrown if an IO error occurred. 595 */ 596 @Override 597 public Map execute(FileSystem fs) throws IOException { 598 FileStatus[] fileStatuses = fs.listStatus(path, filter); 599 return toJson(fileStatuses, fs.getFileStatus(path).isFile()); 600 } 601 602 @Override 603 public boolean accept(Path path) { 604 return true; 605 } 606 607 } 608 609 /** 610 * Executor that performs a batched directory listing. 611 */ 612 @InterfaceAudience.Private 613 public static class FSListStatusBatch implements FileSystemAccess 614 .FileSystemExecutor<Map> { 615 private final Path path; 616 private final byte[] token; 617 618 public FSListStatusBatch(String path, byte[] token) throws IOException { 619 this.path = new Path(path); 620 this.token = token.clone(); 621 } 622 623 /** 624 * Simple wrapper filesystem that exposes the protected batched 625 * listStatus API so we can use it. 626 */ 627 private static class WrappedFileSystem extends FilterFileSystem { 628 public WrappedFileSystem(FileSystem f) { 629 super(f); 630 } 631 632 @Override 633 public DirectoryEntries listStatusBatch(Path f, byte[] token) throws 634 FileNotFoundException, IOException { 635 return super.listStatusBatch(f, token); 636 } 637 } 638 639 @Override 640 public Map execute(FileSystem fs) throws IOException { 641 WrappedFileSystem wrappedFS = new WrappedFileSystem(fs); 642 FileSystem.DirectoryEntries entries = 643 wrappedFS.listStatusBatch(path, token); 644 return toJson(entries, wrappedFS.getFileStatus(path).isFile()); 645 } 646 } 647 648 /** 649 * Executor that performs a mkdirs FileSystemAccess files system operation. 650 */ 651 @InterfaceAudience.Private 652 public static class FSMkdirs implements FileSystemAccess.FileSystemExecutor<JSONObject> { 653 654 private Path path; 655 private short permission; 656 657 /** 658 * Creates a mkdirs executor. 659 * 660 * @param path directory path to create. 661 * @param permission permission to use. 662 */ 663 public FSMkdirs(String path, short permission) { 664 this.path = new Path(path); 665 this.permission = permission; 666 } 667 668 /** 669 * Executes the filesystem operation. 670 * 671 * @param fs filesystem instance to use. 672 * 673 * @return <code>true</code> if the mkdirs operation was successful, 674 * <code>false</code> otherwise. 675 * 676 * @throws IOException thrown if an IO error occured. 677 */ 678 @Override 679 public JSONObject execute(FileSystem fs) throws IOException { 680 FsPermission fsPermission = new FsPermission(permission); 681 boolean mkdirs = fs.mkdirs(path, fsPermission); 682 return toJSON(HttpFSFileSystem.MKDIRS_JSON, mkdirs); 683 } 684 685 } 686 687 /** 688 * Executor that performs a open FileSystemAccess files system operation. 689 */ 690 @InterfaceAudience.Private 691 public static class FSOpen implements FileSystemAccess.FileSystemExecutor<InputStream> { 692 private Path path; 693 694 /** 695 * Creates a open executor. 696 * 697 * @param path file to open. 698 */ 699 public FSOpen(String path) { 700 this.path = new Path(path); 701 } 702 703 /** 704 * Executes the filesystem operation. 705 * 706 * @param fs filesystem instance to use. 707 * 708 * @return The inputstream of the file. 709 * 710 * @throws IOException thrown if an IO error occured. 711 */ 712 @Override 713 public InputStream execute(FileSystem fs) throws IOException { 714 int bufferSize = HttpFSServerWebApp.get().getConfig().getInt("httpfs.buffer.size", 4096); 715 return fs.open(path, bufferSize); 716 } 717 718 } 719 720 /** 721 * Executor that performs a rename FileSystemAccess files system operation. 722 */ 723 @InterfaceAudience.Private 724 public static class FSRename implements FileSystemAccess.FileSystemExecutor<JSONObject> { 725 private Path path; 726 private Path toPath; 727 728 /** 729 * Creates a rename executor. 730 * 731 * @param path path to rename. 732 * @param toPath new name. 733 */ 734 public FSRename(String path, String toPath) { 735 this.path = new Path(path); 736 this.toPath = new Path(toPath); 737 } 738 739 /** 740 * Executes the filesystem operation. 741 * 742 * @param fs filesystem instance to use. 743 * 744 * @return <code>true</code> if the rename operation was successful, 745 * <code>false</code> otherwise. 746 * 747 * @throws IOException thrown if an IO error occured. 748 */ 749 @Override 750 public JSONObject execute(FileSystem fs) throws IOException { 751 boolean renamed = fs.rename(path, toPath); 752 return toJSON(HttpFSFileSystem.RENAME_JSON, renamed); 753 } 754 755 } 756 757 /** 758 * Executor that performs a set-owner FileSystemAccess files system operation. 759 */ 760 @InterfaceAudience.Private 761 public static class FSSetOwner implements FileSystemAccess.FileSystemExecutor<Void> { 762 private Path path; 763 private String owner; 764 private String group; 765 766 /** 767 * Creates a set-owner executor. 768 * 769 * @param path the path to set the owner. 770 * @param owner owner to set. 771 * @param group group to set. 772 */ 773 public FSSetOwner(String path, String owner, String group) { 774 this.path = new Path(path); 775 this.owner = owner; 776 this.group = group; 777 } 778 779 /** 780 * Executes the filesystem operation. 781 * 782 * @param fs filesystem instance to use. 783 * 784 * @return void. 785 * 786 * @throws IOException thrown if an IO error occured. 787 */ 788 @Override 789 public Void execute(FileSystem fs) throws IOException { 790 fs.setOwner(path, owner, group); 791 return null; 792 } 793 794 } 795 796 /** 797 * Executor that performs a set-permission FileSystemAccess files system operation. 798 */ 799 @InterfaceAudience.Private 800 public static class FSSetPermission implements FileSystemAccess.FileSystemExecutor<Void> { 801 802 private Path path; 803 private short permission; 804 805 /** 806 * Creates a set-permission executor. 807 * 808 * @param path path to set the permission. 809 * @param permission permission to set. 810 */ 811 public FSSetPermission(String path, short permission) { 812 this.path = new Path(path); 813 this.permission = permission; 814 } 815 816 /** 817 * Executes the filesystem operation. 818 * 819 * @param fs filesystem instance to use. 820 * 821 * @return void. 822 * 823 * @throws IOException thrown if an IO error occured. 824 */ 825 @Override 826 public Void execute(FileSystem fs) throws IOException { 827 FsPermission fsPermission = new FsPermission(permission); 828 fs.setPermission(path, fsPermission); 829 return null; 830 } 831 832 } 833 834 /** 835 * Executor that sets the acl for a file in a FileSystem 836 */ 837 @InterfaceAudience.Private 838 public static class FSSetAcl implements FileSystemAccess.FileSystemExecutor<Void> { 839 840 private Path path; 841 private List<AclEntry> aclEntries; 842 843 /** 844 * Creates a set-acl executor. 845 * 846 * @param path path to set the acl. 847 * @param aclSpec acl to set. 848 */ 849 public FSSetAcl(String path, String aclSpec) { 850 this.path = new Path(path); 851 this.aclEntries = AclEntry.parseAclSpec(aclSpec, true); 852 } 853 854 /** 855 * Executes the filesystem operation. 856 * 857 * @param fs filesystem instance to use. 858 * 859 * @return void. 860 * 861 * @throws IOException thrown if an IO error occurred. 862 */ 863 @Override 864 public Void execute(FileSystem fs) throws IOException { 865 fs.setAcl(path, aclEntries); 866 return null; 867 } 868 869 } 870 871 /** 872 * Executor that removes all acls from a file in a FileSystem 873 */ 874 @InterfaceAudience.Private 875 public static class FSRemoveAcl implements FileSystemAccess.FileSystemExecutor<Void> { 876 877 private Path path; 878 879 /** 880 * Creates a remove-acl executor. 881 * 882 * @param path path from which to remove the acl. 883 */ 884 public FSRemoveAcl(String path) { 885 this.path = new Path(path); 886 } 887 888 /** 889 * Executes the filesystem operation. 890 * 891 * @param fs filesystem instance to use. 892 * 893 * @return void. 894 * 895 * @throws IOException thrown if an IO error occurred. 896 */ 897 @Override 898 public Void execute(FileSystem fs) throws IOException { 899 fs.removeAcl(path); 900 return null; 901 } 902 903 } 904 905 /** 906 * Executor that modifies acl entries for a file in a FileSystem 907 */ 908 @InterfaceAudience.Private 909 public static class FSModifyAclEntries implements FileSystemAccess.FileSystemExecutor<Void> { 910 911 private Path path; 912 private List<AclEntry> aclEntries; 913 914 /** 915 * Creates a modify-acl executor. 916 * 917 * @param path path to set the acl. 918 * @param aclSpec acl to set. 919 */ 920 public FSModifyAclEntries(String path, String aclSpec) { 921 this.path = new Path(path); 922 this.aclEntries = AclEntry.parseAclSpec(aclSpec, true); 923 } 924 925 /** 926 * Executes the filesystem operation. 927 * 928 * @param fs filesystem instance to use. 929 * 930 * @return void. 931 * 932 * @throws IOException thrown if an IO error occurred. 933 */ 934 @Override 935 public Void execute(FileSystem fs) throws IOException { 936 fs.modifyAclEntries(path, aclEntries); 937 return null; 938 } 939 940 } 941 942 /** 943 * Executor that removes acl entries from a file in a FileSystem 944 */ 945 @InterfaceAudience.Private 946 public static class FSRemoveAclEntries implements FileSystemAccess.FileSystemExecutor<Void> { 947 948 private Path path; 949 private List<AclEntry> aclEntries; 950 951 /** 952 * Creates a remove acl entry executor. 953 * 954 * @param path path to set the acl. 955 * @param aclSpec acl parts to remove. 956 */ 957 public FSRemoveAclEntries(String path, String aclSpec) { 958 this.path = new Path(path); 959 this.aclEntries = AclEntry.parseAclSpec(aclSpec, false); 960 } 961 962 /** 963 * Executes the filesystem operation. 964 * 965 * @param fs filesystem instance to use. 966 * 967 * @return void. 968 * 969 * @throws IOException thrown if an IO error occurred. 970 */ 971 @Override 972 public Void execute(FileSystem fs) throws IOException { 973 fs.removeAclEntries(path, aclEntries); 974 return null; 975 } 976 977 } 978 979 /** 980 * Executor that removes the default acl from a directory in a FileSystem 981 */ 982 @InterfaceAudience.Private 983 public static class FSRemoveDefaultAcl implements FileSystemAccess.FileSystemExecutor<Void> { 984 985 private Path path; 986 987 /** 988 * Creates an executor for removing the default acl. 989 * 990 * @param path path to set the acl. 991 */ 992 public FSRemoveDefaultAcl(String path) { 993 this.path = new Path(path); 994 } 995 996 /** 997 * Executes the filesystem operation. 998 * 999 * @param fs filesystem instance to use. 1000 * 1001 * @return void. 1002 * 1003 * @throws IOException thrown if an IO error occurred. 1004 */ 1005 @Override 1006 public Void execute(FileSystem fs) throws IOException { 1007 fs.removeDefaultAcl(path); 1008 return null; 1009 } 1010 1011 } 1012 1013 /** 1014 * Executor that performs getting trash root FileSystemAccess 1015 * files system operation. 1016 */ 1017 @InterfaceAudience.Private 1018 public static class FSTrashRoot 1019 implements FileSystemAccess.FileSystemExecutor<JSONObject> { 1020 private Path path; 1021 public FSTrashRoot(String path) { 1022 this.path = new Path(path); 1023 } 1024 1025 @Override 1026 @SuppressWarnings("unchecked") 1027 public JSONObject execute(FileSystem fs) throws IOException { 1028 Path trashRoot = fs.getTrashRoot(this.path); 1029 JSONObject json = new JSONObject(); 1030 json.put(HttpFSFileSystem.TRASH_DIR_JSON, trashRoot.toUri().getPath()); 1031 return json; 1032 } 1033 1034 } 1035 1036 /** 1037 * Executor that gets the ACL information for a given file. 1038 */ 1039 @InterfaceAudience.Private 1040 public static class FSAclStatus implements FileSystemAccess.FileSystemExecutor<Map> { 1041 private Path path; 1042 1043 /** 1044 * Creates an executor for getting the ACLs for a file. 1045 * 1046 * @param path the path to retrieve the ACLs. 1047 */ 1048 public FSAclStatus(String path) { 1049 this.path = new Path(path); 1050 } 1051 1052 /** 1053 * Executes the filesystem operation. 1054 * 1055 * @param fs filesystem instance to use. 1056 * 1057 * @return a Map object (JSON friendly) with the file status. 1058 * 1059 * @throws IOException thrown if an IO error occurred. 1060 */ 1061 @Override 1062 public Map execute(FileSystem fs) throws IOException { 1063 AclStatus status = fs.getAclStatus(path); 1064 return aclStatusToJSON(status); 1065 } 1066 1067 } 1068 1069 /** 1070 * Executor that performs a set-replication FileSystemAccess files system operation. 1071 */ 1072 @InterfaceAudience.Private 1073 public static class FSSetReplication implements FileSystemAccess.FileSystemExecutor<JSONObject> { 1074 private Path path; 1075 private short replication; 1076 1077 /** 1078 * Creates a set-replication executor. 1079 * 1080 * @param path path to set the replication factor. 1081 * @param replication replication factor to set. 1082 */ 1083 public FSSetReplication(String path, short replication) { 1084 this.path = new Path(path); 1085 this.replication = replication; 1086 } 1087 1088 /** 1089 * Executes the filesystem operation. 1090 * 1091 * @param fs filesystem instance to use. 1092 * 1093 * @return <code>true</code> if the replication value was set, 1094 * <code>false</code> otherwise. 1095 * 1096 * @throws IOException thrown if an IO error occured. 1097 */ 1098 @Override 1099 @SuppressWarnings("unchecked") 1100 public JSONObject execute(FileSystem fs) throws IOException { 1101 boolean ret = fs.setReplication(path, replication); 1102 JSONObject json = new JSONObject(); 1103 json.put(HttpFSFileSystem.SET_REPLICATION_JSON, ret); 1104 return json; 1105 } 1106 1107 } 1108 1109 /** 1110 * Executor that performs a set-times FileSystemAccess files system operation. 1111 */ 1112 @InterfaceAudience.Private 1113 public static class FSSetTimes implements FileSystemAccess.FileSystemExecutor<Void> { 1114 private Path path; 1115 private long mTime; 1116 private long aTime; 1117 1118 /** 1119 * Creates a set-times executor. 1120 * 1121 * @param path path to set the times. 1122 * @param mTime modified time to set. 1123 * @param aTime access time to set. 1124 */ 1125 public FSSetTimes(String path, long mTime, long aTime) { 1126 this.path = new Path(path); 1127 this.mTime = mTime; 1128 this.aTime = aTime; 1129 } 1130 1131 /** 1132 * Executes the filesystem operation. 1133 * 1134 * @param fs filesystem instance to use. 1135 * 1136 * @return void. 1137 * 1138 * @throws IOException thrown if an IO error occured. 1139 */ 1140 @Override 1141 public Void execute(FileSystem fs) throws IOException { 1142 fs.setTimes(path, mTime, aTime); 1143 return null; 1144 } 1145 1146 } 1147 1148 /** 1149 * Executor that performs a setxattr FileSystemAccess files system operation. 1150 */ 1151 @InterfaceAudience.Private 1152 public static class FSSetXAttr implements 1153 FileSystemAccess.FileSystemExecutor<Void> { 1154 1155 private Path path; 1156 private String name; 1157 private byte[] value; 1158 private EnumSet<XAttrSetFlag> flag; 1159 1160 public FSSetXAttr(String path, String name, String encodedValue, 1161 EnumSet<XAttrSetFlag> flag) throws IOException { 1162 this.path = new Path(path); 1163 this.name = name; 1164 this.value = XAttrCodec.decodeValue(encodedValue); 1165 this.flag = flag; 1166 } 1167 1168 @Override 1169 public Void execute(FileSystem fs) throws IOException { 1170 fs.setXAttr(path, name, value, flag); 1171 return null; 1172 } 1173 } 1174 1175 /** 1176 * Executor that performs a removexattr FileSystemAccess files system 1177 * operation. 1178 */ 1179 @InterfaceAudience.Private 1180 public static class FSRemoveXAttr implements 1181 FileSystemAccess.FileSystemExecutor<Void> { 1182 1183 private Path path; 1184 private String name; 1185 1186 public FSRemoveXAttr(String path, String name) { 1187 this.path = new Path(path); 1188 this.name = name; 1189 } 1190 1191 @Override 1192 public Void execute(FileSystem fs) throws IOException { 1193 fs.removeXAttr(path, name); 1194 return null; 1195 } 1196 } 1197 1198 /** 1199 * Executor that performs listing xattrs FileSystemAccess files system 1200 * operation. 1201 */ 1202 @SuppressWarnings("rawtypes") 1203 @InterfaceAudience.Private 1204 public static class FSListXAttrs implements 1205 FileSystemAccess.FileSystemExecutor<Map> { 1206 private Path path; 1207 1208 /** 1209 * Creates listing xattrs executor. 1210 * 1211 * @param path the path to retrieve the xattrs. 1212 */ 1213 public FSListXAttrs(String path) { 1214 this.path = new Path(path); 1215 } 1216 1217 /** 1218 * Executes the filesystem operation. 1219 * 1220 * @param fs filesystem instance to use. 1221 * 1222 * @return Map a map object (JSON friendly) with the xattr names. 1223 * 1224 * @throws IOException thrown if an IO error occured. 1225 */ 1226 @Override 1227 public Map execute(FileSystem fs) throws IOException { 1228 List<String> names = fs.listXAttrs(path); 1229 return xAttrNamesToJSON(names); 1230 } 1231 } 1232 1233 /** 1234 * Executor that performs getting xattrs FileSystemAccess files system 1235 * operation. 1236 */ 1237 @SuppressWarnings("rawtypes") 1238 @InterfaceAudience.Private 1239 public static class FSGetXAttrs implements 1240 FileSystemAccess.FileSystemExecutor<Map> { 1241 private Path path; 1242 private List<String> names; 1243 private XAttrCodec encoding; 1244 1245 /** 1246 * Creates getting xattrs executor. 1247 * 1248 * @param path the path to retrieve the xattrs. 1249 */ 1250 public FSGetXAttrs(String path, List<String> names, XAttrCodec encoding) { 1251 this.path = new Path(path); 1252 this.names = names; 1253 this.encoding = encoding; 1254 } 1255 1256 /** 1257 * Executes the filesystem operation. 1258 * 1259 * @param fs filesystem instance to use. 1260 * 1261 * @return Map a map object (JSON friendly) with the xattrs. 1262 * 1263 * @throws IOException thrown if an IO error occured. 1264 */ 1265 @Override 1266 public Map execute(FileSystem fs) throws IOException { 1267 Map<String, byte[]> xattrs = null; 1268 if (names != null && !names.isEmpty()) { 1269 xattrs = fs.getXAttrs(path, names); 1270 } else { 1271 xattrs = fs.getXAttrs(path); 1272 } 1273 return xAttrsToJSON(xattrs, encoding); 1274 } 1275 } 1276}