001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.fs;
020
021import java.io.*;
022import java.net.URI;
023import java.net.URISyntaxException;
024import java.util.EnumSet;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.hadoop.classification.InterfaceAudience;
029import org.apache.hadoop.classification.InterfaceStability;
030import org.apache.hadoop.conf.Configuration;
031import org.apache.hadoop.fs.permission.AclEntry;
032import org.apache.hadoop.fs.permission.AclStatus;
033import org.apache.hadoop.fs.permission.FsAction;
034import org.apache.hadoop.fs.permission.FsPermission;
035import org.apache.hadoop.fs.Options.ChecksumOpt;
036import org.apache.hadoop.security.AccessControlException;
037import org.apache.hadoop.util.Progressable;
038
039/****************************************************************
040 * A <code>FilterFileSystem</code> contains
041 * some other file system, which it uses as
042 * its  basic file system, possibly transforming
043 * the data along the way or providing  additional
044 * functionality. The class <code>FilterFileSystem</code>
045 * itself simply overrides all  methods of
046 * <code>FileSystem</code> with versions that
047 * pass all requests to the contained  file
048 * system. Subclasses of <code>FilterFileSystem</code>
049 * may further override some of  these methods
050 * and may also provide additional methods
051 * and fields.
052 *
053 *****************************************************************/
054@InterfaceAudience.Public
055@InterfaceStability.Stable
056public class FilterFileSystem extends FileSystem {
057  
058  protected FileSystem fs;
059  protected String swapScheme;
060  
061  /*
062   * so that extending classes can define it
063   */
064  public FilterFileSystem() {
065  }
066  
067  public FilterFileSystem(FileSystem fs) {
068    this.fs = fs;
069    this.statistics = fs.statistics;
070  }
071
072  /**
073   * Get the raw file system 
074   * @return FileSystem being filtered
075   */
076  public FileSystem getRawFileSystem() {
077    return fs;
078  }
079
080  /** Called after a new FileSystem instance is constructed.
081   * @param name a uri whose authority section names the host, port, etc.
082   *   for this FileSystem
083   * @param conf the configuration
084   */
085  @Override
086  public void initialize(URI name, Configuration conf) throws IOException {
087    super.initialize(name, conf);
088    // this is less than ideal, but existing filesystems sometimes neglect
089    // to initialize the embedded filesystem
090    if (fs.getConf() == null) {
091      fs.initialize(name, conf);
092    }
093    String scheme = name.getScheme();
094    if (!scheme.equals(fs.getUri().getScheme())) {
095      swapScheme = scheme;
096    }
097  }
098
099  /** Returns a URI whose scheme and authority identify this FileSystem.*/
100  @Override
101  public URI getUri() {
102    return fs.getUri();
103  }
104  
105  
106  @Override
107  protected URI getCanonicalUri() {
108    return fs.getCanonicalUri();
109  }
110
111  @Override
112  protected URI canonicalizeUri(URI uri) {
113    return fs.canonicalizeUri(uri);
114  }
115
116  /** Make sure that a path specifies a FileSystem. */
117  @Override
118  public Path makeQualified(Path path) {
119    Path fqPath = fs.makeQualified(path);
120    // swap in our scheme if the filtered fs is using a different scheme
121    if (swapScheme != null) {
122      try {
123        // NOTE: should deal with authority, but too much other stuff is broken 
124        fqPath = new Path(
125            new URI(swapScheme, fqPath.toUri().getSchemeSpecificPart(), null)
126        );
127      } catch (URISyntaxException e) {
128        throw new IllegalArgumentException(e);
129      }
130    }
131    return fqPath;
132  }
133  
134  ///////////////////////////////////////////////////////////////
135  // FileSystem
136  ///////////////////////////////////////////////////////////////
137
138  /** Check that a Path belongs to this FileSystem. */
139  @Override
140  protected void checkPath(Path path) {
141    fs.checkPath(path);
142  }
143
144  @Override
145  public BlockLocation[] getFileBlockLocations(FileStatus file, long start,
146    long len) throws IOException {
147      return fs.getFileBlockLocations(file, start, len);
148  }
149
150  @Override
151  public Path resolvePath(final Path p) throws IOException {
152    return fs.resolvePath(p);
153  }
154  /**
155   * Opens an FSDataInputStream at the indicated Path.
156   * @param f the file name to open
157   * @param bufferSize the size of the buffer to be used.
158   */
159  @Override
160  public FSDataInputStream open(Path f, int bufferSize) throws IOException {
161    return fs.open(f, bufferSize);
162  }
163
164  @Override
165  public FSDataOutputStream append(Path f, int bufferSize,
166      Progressable progress) throws IOException {
167    return fs.append(f, bufferSize, progress);
168  }
169
170  @Override
171  public void concat(Path f, Path[] psrcs) throws IOException {
172    fs.concat(f, psrcs);
173  }
174
175  @Override
176  public FSDataOutputStream create(Path f, FsPermission permission,
177      boolean overwrite, int bufferSize, short replication, long blockSize,
178      Progressable progress) throws IOException {
179    return fs.create(f, permission,
180        overwrite, bufferSize, replication, blockSize, progress);
181  }
182
183  @Override
184  public FSDataOutputStream create(Path f,
185        FsPermission permission,
186        EnumSet<CreateFlag> flags,
187        int bufferSize,
188        short replication,
189        long blockSize,
190        Progressable progress,
191        ChecksumOpt checksumOpt) throws IOException {
192    return fs.create(f, permission,
193      flags, bufferSize, replication, blockSize, progress, checksumOpt);
194  }
195  
196  @Override
197  @Deprecated
198  public FSDataOutputStream createNonRecursive(Path f, FsPermission permission,
199      EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize,
200      Progressable progress) throws IOException {
201    
202    return fs.createNonRecursive(f, permission, flags, bufferSize, replication, blockSize,
203        progress);
204  }
205
206  /**
207   * Set replication for an existing file.
208   * 
209   * @param src file name
210   * @param replication new replication
211   * @throws IOException
212   * @return true if successful;
213   *         false if file does not exist or is a directory
214   */
215  @Override
216  public boolean setReplication(Path src, short replication) throws IOException {
217    return fs.setReplication(src, replication);
218  }
219  
220  /**
221   * Renames Path src to Path dst.  Can take place on local fs
222   * or remote DFS.
223   */
224  @Override
225  public boolean rename(Path src, Path dst) throws IOException {
226    return fs.rename(src, dst);
227  }
228
229  @Override
230  public boolean truncate(Path f, final long newLength) throws IOException {
231    return fs.truncate(f, newLength);
232  }
233  
234  /** Delete a file */
235  @Override
236  public boolean delete(Path f, boolean recursive) throws IOException {
237    return fs.delete(f, recursive);
238  }
239  
240  /** List files in a directory. */
241  @Override
242  public FileStatus[] listStatus(Path f) throws IOException {
243    return fs.listStatus(f);
244  }
245
246  @Override
247  public RemoteIterator<Path> listCorruptFileBlocks(Path path)
248    throws IOException {
249    return fs.listCorruptFileBlocks(path);
250  }
251
252  /** List files and its block locations in a directory. */
253  @Override
254  public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f)
255  throws IOException {
256    return fs.listLocatedStatus(f);
257  }
258  
259  /** Return a remote iterator for listing in a directory */
260  @Override
261  public RemoteIterator<FileStatus> listStatusIterator(Path f)
262  throws IOException {
263    return fs.listStatusIterator(f);
264   }
265
266  @Override
267  public Path getHomeDirectory() {
268    return fs.getHomeDirectory();
269  }
270
271
272  /**
273   * Set the current working directory for the given file system. All relative
274   * paths will be resolved relative to it.
275   * 
276   * @param newDir
277   */
278  @Override
279  public void setWorkingDirectory(Path newDir) {
280    fs.setWorkingDirectory(newDir);
281  }
282  
283  /**
284   * Get the current working directory for the given file system
285   * 
286   * @return the directory pathname
287   */
288  @Override
289  public Path getWorkingDirectory() {
290    return fs.getWorkingDirectory();
291  }
292  
293  @Override
294  protected Path getInitialWorkingDirectory() {
295    return fs.getInitialWorkingDirectory();
296  }
297  
298  @Override
299  public FsStatus getStatus(Path p) throws IOException {
300    return fs.getStatus(p);
301  }
302  
303  @Override
304  public boolean mkdirs(Path f, FsPermission permission) throws IOException {
305    return fs.mkdirs(f, permission);
306  }
307
308
309  /**
310   * The src file is on the local disk.  Add it to FS at
311   * the given dst name.
312   * delSrc indicates if the source should be removed
313   */
314  @Override
315  public void copyFromLocalFile(boolean delSrc, Path src, Path dst)
316    throws IOException {
317    fs.copyFromLocalFile(delSrc, src, dst);
318  }
319  
320  /**
321   * The src files are on the local disk.  Add it to FS at
322   * the given dst name.
323   * delSrc indicates if the source should be removed
324   */
325  @Override
326  public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
327                                Path[] srcs, Path dst)
328    throws IOException {
329    fs.copyFromLocalFile(delSrc, overwrite, srcs, dst);
330  }
331  
332  /**
333   * The src file is on the local disk.  Add it to FS at
334   * the given dst name.
335   * delSrc indicates if the source should be removed
336   */
337  @Override
338  public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
339                                Path src, Path dst)
340    throws IOException {
341    fs.copyFromLocalFile(delSrc, overwrite, src, dst);
342  }
343
344  /**
345   * The src file is under FS, and the dst is on the local disk.
346   * Copy it from FS control to the local dst name.
347   * delSrc indicates if the src will be removed or not.
348   */   
349  @Override
350  public void copyToLocalFile(boolean delSrc, Path src, Path dst)
351    throws IOException {
352    fs.copyToLocalFile(delSrc, src, dst);
353  }
354  
355  /**
356   * Returns a local File that the user can write output to.  The caller
357   * provides both the eventual FS target name and the local working
358   * file.  If the FS is local, we write directly into the target.  If
359   * the FS is remote, we write into the tmp local area.
360   */
361  @Override
362  public Path startLocalOutput(Path fsOutputFile, Path tmpLocalFile)
363    throws IOException {
364    return fs.startLocalOutput(fsOutputFile, tmpLocalFile);
365  }
366
367  /**
368   * Called when we're all done writing to the target.  A local FS will
369   * do nothing, because we've written to exactly the right place.  A remote
370   * FS will copy the contents of tmpLocalFile to the correct target at
371   * fsOutputFile.
372   */
373  @Override
374  public void completeLocalOutput(Path fsOutputFile, Path tmpLocalFile)
375    throws IOException {
376    fs.completeLocalOutput(fsOutputFile, tmpLocalFile);
377  }
378
379  /** Return the total size of all files in the filesystem.*/
380  @Override
381  public long getUsed() throws IOException{
382    return fs.getUsed();
383  }
384  
385  @Override
386  public long getDefaultBlockSize() {
387    return fs.getDefaultBlockSize();
388  }
389  
390  @Override
391  public short getDefaultReplication() {
392    return fs.getDefaultReplication();
393  }
394
395  @Override
396  public FsServerDefaults getServerDefaults() throws IOException {
397    return fs.getServerDefaults();
398  }
399
400  // path variants delegate to underlying filesystem 
401  @Override
402  public long getDefaultBlockSize(Path f) {
403    return fs.getDefaultBlockSize(f);
404  }
405
406  @Override
407  public short getDefaultReplication(Path f) {
408    return fs.getDefaultReplication(f);
409  }
410
411  @Override
412  public FsServerDefaults getServerDefaults(Path f) throws IOException {
413    return fs.getServerDefaults(f);
414  }
415
416  /**
417   * Get file status.
418   */
419  @Override
420  public FileStatus getFileStatus(Path f) throws IOException {
421    return fs.getFileStatus(f);
422  }
423
424  @Override
425  public void access(Path path, FsAction mode) throws AccessControlException,
426      FileNotFoundException, IOException {
427    fs.access(path, mode);
428  }
429
430  public void createSymlink(final Path target, final Path link,
431      final boolean createParent) throws AccessControlException,
432      FileAlreadyExistsException, FileNotFoundException,
433      ParentNotDirectoryException, UnsupportedFileSystemException, 
434      IOException {
435    fs.createSymlink(target, link, createParent);
436  }
437
438  public FileStatus getFileLinkStatus(final Path f)
439      throws AccessControlException, FileNotFoundException,
440      UnsupportedFileSystemException, IOException {
441    return fs.getFileLinkStatus(f);
442  }
443
444  public boolean supportsSymlinks() {
445    return fs.supportsSymlinks();
446  }
447
448  public Path getLinkTarget(Path f) throws IOException {
449    return fs.getLinkTarget(f);
450  }
451
452  protected Path resolveLink(Path f) throws IOException {
453    return fs.resolveLink(f);
454  }
455
456  @Override
457  public FileChecksum getFileChecksum(Path f) throws IOException {
458    return fs.getFileChecksum(f);
459  }
460
461  @Override
462  public FileChecksum getFileChecksum(Path f, long length) throws IOException {
463    return fs.getFileChecksum(f, length);
464  }
465
466  @Override
467  public void setVerifyChecksum(boolean verifyChecksum) {
468    fs.setVerifyChecksum(verifyChecksum);
469  }
470  
471  @Override
472  public void setWriteChecksum(boolean writeChecksum) {
473    fs.setWriteChecksum(writeChecksum);
474  }
475
476  @Override
477  public Configuration getConf() {
478    return fs.getConf();
479  }
480  
481  @Override
482  public void close() throws IOException {
483    super.close();
484    fs.close();
485  }
486
487  @Override
488  public void setOwner(Path p, String username, String groupname
489      ) throws IOException {
490    fs.setOwner(p, username, groupname);
491  }
492
493  @Override
494  public void setTimes(Path p, long mtime, long atime
495      ) throws IOException {
496    fs.setTimes(p, mtime, atime);
497  }
498
499  @Override
500  public void setPermission(Path p, FsPermission permission
501      ) throws IOException {
502    fs.setPermission(p, permission);
503  }
504
505  @Override
506  protected FSDataOutputStream primitiveCreate(Path f,
507      FsPermission absolutePermission, EnumSet<CreateFlag> flag,
508      int bufferSize, short replication, long blockSize,
509      Progressable progress, ChecksumOpt checksumOpt)
510      throws IOException {
511    return fs.primitiveCreate(f, absolutePermission, flag,
512        bufferSize, replication, blockSize, progress, checksumOpt);
513  }
514
515  @Override
516  @SuppressWarnings("deprecation")
517  protected boolean primitiveMkdir(Path f, FsPermission abdolutePermission)
518      throws IOException {
519    return fs.primitiveMkdir(f, abdolutePermission);
520  }
521  
522  @Override // FileSystem
523  public FileSystem[] getChildFileSystems() {
524    return new FileSystem[]{fs};
525  }
526
527  @Override // FileSystem
528  public Path createSnapshot(Path path, String snapshotName)
529      throws IOException {
530    return fs.createSnapshot(path, snapshotName);
531  }
532  
533  @Override // FileSystem
534  public void renameSnapshot(Path path, String snapshotOldName,
535      String snapshotNewName) throws IOException {
536    fs.renameSnapshot(path, snapshotOldName, snapshotNewName);
537  }
538  
539  @Override // FileSystem
540  public void deleteSnapshot(Path path, String snapshotName)
541      throws IOException {
542    fs.deleteSnapshot(path, snapshotName);
543  }
544
545  @Override
546  public void modifyAclEntries(Path path, List<AclEntry> aclSpec)
547      throws IOException {
548    fs.modifyAclEntries(path, aclSpec);
549  }
550
551  @Override
552  public void removeAclEntries(Path path, List<AclEntry> aclSpec)
553      throws IOException {
554    fs.removeAclEntries(path, aclSpec);
555  }
556
557  @Override
558  public void removeDefaultAcl(Path path) throws IOException {
559    fs.removeDefaultAcl(path);
560  }
561
562  @Override
563  public void removeAcl(Path path) throws IOException {
564    fs.removeAcl(path);
565  }
566
567  @Override
568  public void setAcl(Path path, List<AclEntry> aclSpec) throws IOException {
569    fs.setAcl(path, aclSpec);
570  }
571
572  @Override
573  public AclStatus getAclStatus(Path path) throws IOException {
574    return fs.getAclStatus(path);
575  }
576
577  @Override
578  public void setXAttr(Path path, String name, byte[] value)
579      throws IOException {
580    fs.setXAttr(path, name, value);
581  }
582
583  @Override
584  public void setXAttr(Path path, String name, byte[] value,
585      EnumSet<XAttrSetFlag> flag) throws IOException {
586    fs.setXAttr(path, name, value, flag);
587  }
588
589  @Override
590  public byte[] getXAttr(Path path, String name) throws IOException {
591    return fs.getXAttr(path, name);
592  }
593
594  @Override
595  public Map<String, byte[]> getXAttrs(Path path) throws IOException {
596    return fs.getXAttrs(path);
597  }
598
599  @Override
600  public Map<String, byte[]> getXAttrs(Path path, List<String> names)
601      throws IOException {
602    return fs.getXAttrs(path, names);
603  }
604
605  @Override
606  public List<String> listXAttrs(Path path) throws IOException {
607    return fs.listXAttrs(path);
608  }
609
610  @Override
611  public void removeXAttr(Path path, String name) throws IOException {
612    fs.removeXAttr(path, name);
613  }
614}