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    
027    import org.apache.hadoop.classification.InterfaceAudience;
028    import org.apache.hadoop.classification.InterfaceStability;
029    import org.apache.hadoop.conf.Configuration;
030    import org.apache.hadoop.fs.permission.AclEntry;
031    import org.apache.hadoop.fs.permission.AclStatus;
032    import org.apache.hadoop.fs.permission.FsPermission;
033    import org.apache.hadoop.fs.ContentSummary;
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 void setVerifyChecksum(boolean verifyChecksum) {
433        fs.setVerifyChecksum(verifyChecksum);
434      }
435      
436      @Override
437      public void setWriteChecksum(boolean writeChecksum) {
438        fs.setWriteChecksum(writeChecksum);
439      }
440    
441      @Override
442      public Configuration getConf() {
443        return fs.getConf();
444      }
445      
446      @Override
447      public void close() throws IOException {
448        super.close();
449        fs.close();
450      }
451    
452      @Override
453      public void setOwner(Path p, String username, String groupname
454          ) throws IOException {
455        fs.setOwner(p, username, groupname);
456      }
457    
458      @Override
459      public void setTimes(Path p, long mtime, long atime
460          ) throws IOException {
461        fs.setTimes(p, mtime, atime);
462      }
463    
464      @Override
465      public void setPermission(Path p, FsPermission permission
466          ) throws IOException {
467        fs.setPermission(p, permission);
468      }
469    
470      @Override
471      protected FSDataOutputStream primitiveCreate(Path f,
472          FsPermission absolutePermission, EnumSet<CreateFlag> flag,
473          int bufferSize, short replication, long blockSize,
474          Progressable progress, ChecksumOpt checksumOpt)
475          throws IOException {
476        return fs.primitiveCreate(f, absolutePermission, flag,
477            bufferSize, replication, blockSize, progress, checksumOpt);
478      }
479    
480      @Override
481      @SuppressWarnings("deprecation")
482      protected boolean primitiveMkdir(Path f, FsPermission abdolutePermission)
483          throws IOException {
484        return fs.primitiveMkdir(f, abdolutePermission);
485      }
486      
487      @Override // FileSystem
488      public FileSystem[] getChildFileSystems() {
489        return new FileSystem[]{fs};
490      }
491    
492      @Override // FileSystem
493      public Path createSnapshot(Path path, String snapshotName)
494          throws IOException {
495        return fs.createSnapshot(path, snapshotName);
496      }
497      
498      @Override // FileSystem
499      public void renameSnapshot(Path path, String snapshotOldName,
500          String snapshotNewName) throws IOException {
501        fs.renameSnapshot(path, snapshotOldName, snapshotNewName);
502      }
503      
504      @Override // FileSystem
505      public void deleteSnapshot(Path path, String snapshotName)
506          throws IOException {
507        fs.deleteSnapshot(path, snapshotName);
508      }
509    
510      @Override
511      public void modifyAclEntries(Path path, List<AclEntry> aclSpec)
512          throws IOException {
513        fs.modifyAclEntries(path, aclSpec);
514      }
515    
516      @Override
517      public void removeAclEntries(Path path, List<AclEntry> aclSpec)
518          throws IOException {
519        fs.removeAclEntries(path, aclSpec);
520      }
521    
522      @Override
523      public void removeDefaultAcl(Path path) throws IOException {
524        fs.removeDefaultAcl(path);
525      }
526    
527      @Override
528      public void removeAcl(Path path) throws IOException {
529        fs.removeAcl(path);
530      }
531    
532      @Override
533      public void setAcl(Path path, List<AclEntry> aclSpec) throws IOException {
534        fs.setAcl(path, aclSpec);
535      }
536    
537      @Override
538      public AclStatus getAclStatus(Path path) throws IOException {
539        return fs.getAclStatus(path);
540      }
541    }