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