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