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);
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  /** Delete a file */
230  @Override
231  public boolean delete(Path f, boolean recursive) throws IOException {
232    return fs.delete(f, recursive);
233  }
234  
235  /** List files in a directory. */
236  @Override
237  public FileStatus[] listStatus(Path f) throws IOException {
238    return fs.listStatus(f);
239  }
240
241  @Override
242  public RemoteIterator<Path> listCorruptFileBlocks(Path path)
243    throws IOException {
244    return fs.listCorruptFileBlocks(path);
245  }
246
247  /** List files and its block locations in a directory. */
248  @Override
249  public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f)
250  throws IOException {
251    return fs.listLocatedStatus(f);
252  }
253  
254  @Override
255  public Path getHomeDirectory() {
256    return fs.getHomeDirectory();
257  }
258
259
260  /**
261   * Set the current working directory for the given file system. All relative
262   * paths will be resolved relative to it.
263   * 
264   * @param newDir
265   */
266  @Override
267  public void setWorkingDirectory(Path newDir) {
268    fs.setWorkingDirectory(newDir);
269  }
270  
271  /**
272   * Get the current working directory for the given file system
273   * 
274   * @return the directory pathname
275   */
276  @Override
277  public Path getWorkingDirectory() {
278    return fs.getWorkingDirectory();
279  }
280  
281  @Override
282  protected Path getInitialWorkingDirectory() {
283    return fs.getInitialWorkingDirectory();
284  }
285  
286  @Override
287  public FsStatus getStatus(Path p) throws IOException {
288    return fs.getStatus(p);
289  }
290  
291  @Override
292  public boolean mkdirs(Path f, FsPermission permission) throws IOException {
293    return fs.mkdirs(f, permission);
294  }
295
296
297  /**
298   * The src file is on the local disk.  Add it to FS at
299   * the given dst name.
300   * delSrc indicates if the source should be removed
301   */
302  @Override
303  public void copyFromLocalFile(boolean delSrc, Path src, Path dst)
304    throws IOException {
305    fs.copyFromLocalFile(delSrc, src, dst);
306  }
307  
308  /**
309   * The src files are on the local disk.  Add it to FS at
310   * the given dst name.
311   * delSrc indicates if the source should be removed
312   */
313  @Override
314  public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
315                                Path[] srcs, Path dst)
316    throws IOException {
317    fs.copyFromLocalFile(delSrc, overwrite, srcs, dst);
318  }
319  
320  /**
321   * The src file is 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 src, Path dst)
328    throws IOException {
329    fs.copyFromLocalFile(delSrc, overwrite, src, dst);
330  }
331
332  /**
333   * The src file is under FS, and the dst is on the local disk.
334   * Copy it from FS control to the local dst name.
335   * delSrc indicates if the src will be removed or not.
336   */   
337  @Override
338  public void copyToLocalFile(boolean delSrc, Path src, Path dst)
339    throws IOException {
340    fs.copyToLocalFile(delSrc, src, dst);
341  }
342  
343  /**
344   * Returns a local File that the user can write output to.  The caller
345   * provides both the eventual FS target name and the local working
346   * file.  If the FS is local, we write directly into the target.  If
347   * the FS is remote, we write into the tmp local area.
348   */
349  @Override
350  public Path startLocalOutput(Path fsOutputFile, Path tmpLocalFile)
351    throws IOException {
352    return fs.startLocalOutput(fsOutputFile, tmpLocalFile);
353  }
354
355  /**
356   * Called when we're all done writing to the target.  A local FS will
357   * do nothing, because we've written to exactly the right place.  A remote
358   * FS will copy the contents of tmpLocalFile to the correct target at
359   * fsOutputFile.
360   */
361  @Override
362  public void completeLocalOutput(Path fsOutputFile, Path tmpLocalFile)
363    throws IOException {
364    fs.completeLocalOutput(fsOutputFile, tmpLocalFile);
365  }
366
367  /** Return the total size of all files in the filesystem.*/
368  @Override
369  public long getUsed() throws IOException{
370    return fs.getUsed();
371  }
372  
373  @Override
374  public long getDefaultBlockSize() {
375    return fs.getDefaultBlockSize();
376  }
377  
378  @Override
379  public short getDefaultReplication() {
380    return fs.getDefaultReplication();
381  }
382
383  @Override
384  public FsServerDefaults getServerDefaults() throws IOException {
385    return fs.getServerDefaults();
386  }
387
388  // path variants delegate to underlying filesystem 
389  @Override
390  public long getDefaultBlockSize(Path f) {
391    return fs.getDefaultBlockSize(f);
392  }
393
394  @Override
395  public short getDefaultReplication(Path f) {
396    return fs.getDefaultReplication(f);
397  }
398
399  @Override
400  public FsServerDefaults getServerDefaults(Path f) throws IOException {
401    return fs.getServerDefaults(f);
402  }
403
404  /**
405   * Get file status.
406   */
407  @Override
408  public FileStatus getFileStatus(Path f) throws IOException {
409    return fs.getFileStatus(f);
410  }
411
412  @Override
413  public void access(Path path, FsAction mode) throws AccessControlException,
414      FileNotFoundException, IOException {
415    fs.access(path, mode);
416  }
417
418  public void createSymlink(final Path target, final Path link,
419      final boolean createParent) throws AccessControlException,
420      FileAlreadyExistsException, FileNotFoundException,
421      ParentNotDirectoryException, UnsupportedFileSystemException, 
422      IOException {
423    fs.createSymlink(target, link, createParent);
424  }
425
426  public FileStatus getFileLinkStatus(final Path f)
427      throws AccessControlException, FileNotFoundException,
428      UnsupportedFileSystemException, IOException {
429    return fs.getFileLinkStatus(f);
430  }
431
432  public boolean supportsSymlinks() {
433    return fs.supportsSymlinks();
434  }
435
436  public Path getLinkTarget(Path f) throws IOException {
437    return fs.getLinkTarget(f);
438  }
439
440  protected Path resolveLink(Path f) throws IOException {
441    return fs.resolveLink(f);
442  }
443
444  @Override
445  public FileChecksum getFileChecksum(Path f) throws IOException {
446    return fs.getFileChecksum(f);
447  }
448
449  @Override
450  public FileChecksum getFileChecksum(Path f, long length) throws IOException {
451    return fs.getFileChecksum(f, length);
452  }
453
454  @Override
455  public void setVerifyChecksum(boolean verifyChecksum) {
456    fs.setVerifyChecksum(verifyChecksum);
457  }
458  
459  @Override
460  public void setWriteChecksum(boolean writeChecksum) {
461    fs.setWriteChecksum(writeChecksum);
462  }
463
464  @Override
465  public Configuration getConf() {
466    return fs.getConf();
467  }
468  
469  @Override
470  public void close() throws IOException {
471    super.close();
472    fs.close();
473  }
474
475  @Override
476  public void setOwner(Path p, String username, String groupname
477      ) throws IOException {
478    fs.setOwner(p, username, groupname);
479  }
480
481  @Override
482  public void setTimes(Path p, long mtime, long atime
483      ) throws IOException {
484    fs.setTimes(p, mtime, atime);
485  }
486
487  @Override
488  public void setPermission(Path p, FsPermission permission
489      ) throws IOException {
490    fs.setPermission(p, permission);
491  }
492
493  @Override
494  protected FSDataOutputStream primitiveCreate(Path f,
495      FsPermission absolutePermission, EnumSet<CreateFlag> flag,
496      int bufferSize, short replication, long blockSize,
497      Progressable progress, ChecksumOpt checksumOpt)
498      throws IOException {
499    return fs.primitiveCreate(f, absolutePermission, flag,
500        bufferSize, replication, blockSize, progress, checksumOpt);
501  }
502
503  @Override
504  @SuppressWarnings("deprecation")
505  protected boolean primitiveMkdir(Path f, FsPermission abdolutePermission)
506      throws IOException {
507    return fs.primitiveMkdir(f, abdolutePermission);
508  }
509  
510  @Override // FileSystem
511  public FileSystem[] getChildFileSystems() {
512    return new FileSystem[]{fs};
513  }
514
515  @Override // FileSystem
516  public Path createSnapshot(Path path, String snapshotName)
517      throws IOException {
518    return fs.createSnapshot(path, snapshotName);
519  }
520  
521  @Override // FileSystem
522  public void renameSnapshot(Path path, String snapshotOldName,
523      String snapshotNewName) throws IOException {
524    fs.renameSnapshot(path, snapshotOldName, snapshotNewName);
525  }
526  
527  @Override // FileSystem
528  public void deleteSnapshot(Path path, String snapshotName)
529      throws IOException {
530    fs.deleteSnapshot(path, snapshotName);
531  }
532
533  @Override
534  public void modifyAclEntries(Path path, List<AclEntry> aclSpec)
535      throws IOException {
536    fs.modifyAclEntries(path, aclSpec);
537  }
538
539  @Override
540  public void removeAclEntries(Path path, List<AclEntry> aclSpec)
541      throws IOException {
542    fs.removeAclEntries(path, aclSpec);
543  }
544
545  @Override
546  public void removeDefaultAcl(Path path) throws IOException {
547    fs.removeDefaultAcl(path);
548  }
549
550  @Override
551  public void removeAcl(Path path) throws IOException {
552    fs.removeAcl(path);
553  }
554
555  @Override
556  public void setAcl(Path path, List<AclEntry> aclSpec) throws IOException {
557    fs.setAcl(path, aclSpec);
558  }
559
560  @Override
561  public AclStatus getAclStatus(Path path) throws IOException {
562    return fs.getAclStatus(path);
563  }
564
565  @Override
566  public void setXAttr(Path path, String name, byte[] value)
567      throws IOException {
568    fs.setXAttr(path, name, value);
569  }
570
571  @Override
572  public void setXAttr(Path path, String name, byte[] value,
573      EnumSet<XAttrSetFlag> flag) throws IOException {
574    fs.setXAttr(path, name, value, flag);
575  }
576
577  @Override
578  public byte[] getXAttr(Path path, String name) throws IOException {
579    return fs.getXAttr(path, name);
580  }
581
582  @Override
583  public Map<String, byte[]> getXAttrs(Path path) throws IOException {
584    return fs.getXAttrs(path);
585  }
586
587  @Override
588  public Map<String, byte[]> getXAttrs(Path path, List<String> names)
589      throws IOException {
590    return fs.getXAttrs(path, names);
591  }
592
593  @Override
594  public List<String> listXAttrs(Path path) throws IOException {
595    return fs.listXAttrs(path);
596  }
597
598  @Override
599  public void removeXAttr(Path path, String name) throws IOException {
600    fs.removeXAttr(path, name);
601  }
602}