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 org.apache.hadoop.classification.InterfaceAudience;
026    import org.apache.hadoop.classification.InterfaceStability;
027    import org.apache.hadoop.conf.Configuration;
028    import org.apache.hadoop.fs.permission.FsPermission;
029    import org.apache.hadoop.fs.ContentSummary;
030    import org.apache.hadoop.fs.Options.ChecksumOpt;
031    import org.apache.hadoop.util.Progressable;
032    
033    /****************************************************************
034     * A <code>FilterFileSystem</code> contains
035     * some other file system, which it uses as
036     * its  basic file system, possibly transforming
037     * the data along the way or providing  additional
038     * functionality. The class <code>FilterFileSystem</code>
039     * itself simply overrides all  methods of
040     * <code>FileSystem</code> with versions that
041     * pass all requests to the contained  file
042     * system. Subclasses of <code>FilterFileSystem</code>
043     * may further override some of  these methods
044     * and may also provide additional methods
045     * and fields.
046     *
047     *****************************************************************/
048    @InterfaceAudience.Public
049    @InterfaceStability.Stable
050    public class FilterFileSystem extends FileSystem {
051      
052      protected FileSystem fs;
053      protected String swapScheme;
054      
055      /*
056       * so that extending classes can define it
057       */
058      public FilterFileSystem() {
059      }
060      
061      public FilterFileSystem(FileSystem fs) {
062        this.fs = fs;
063        this.statistics = fs.statistics;
064      }
065    
066      /**
067       * Get the raw file system 
068       * @return FileSystem being filtered
069       */
070      public FileSystem getRawFileSystem() {
071        return fs;
072      }
073    
074      /** Called after a new FileSystem instance is constructed.
075       * @param name a uri whose authority section names the host, port, etc.
076       *   for this FileSystem
077       * @param conf the configuration
078       */
079      @Override
080      public void initialize(URI name, Configuration conf) throws IOException {
081        super.initialize(name, conf);
082        // this is less than ideal, but existing filesystems sometimes neglect
083        // to initialize the embedded filesystem
084        if (fs.getConf() == null) {
085          fs.initialize(name, conf);
086        }
087        String scheme = name.getScheme();
088        if (!scheme.equals(fs.getUri().getScheme())) {
089          swapScheme = scheme;
090        }
091      }
092    
093      /** Returns a URI whose scheme and authority identify this FileSystem.*/
094      @Override
095      public URI getUri() {
096        return fs.getUri();
097      }
098    
099      /**
100       * Returns a qualified URI whose scheme and authority identify this
101       * FileSystem.
102       */
103      @Override
104      protected URI getCanonicalUri() {
105        return fs.getCanonicalUri();
106      }
107      
108      /** Make sure that a path specifies a FileSystem. */
109      @Override
110      public Path makeQualified(Path path) {
111        Path fqPath = fs.makeQualified(path);
112        // swap in our scheme if the filtered fs is using a different scheme
113        if (swapScheme != null) {
114          try {
115            // NOTE: should deal with authority, but too much other stuff is broken 
116            fqPath = new Path(
117                new URI(swapScheme, fqPath.toUri().getSchemeSpecificPart(), null)
118            );
119          } catch (URISyntaxException e) {
120            throw new IllegalArgumentException(e);
121          }
122        }
123        return fqPath;
124      }
125      
126      ///////////////////////////////////////////////////////////////
127      // FileSystem
128      ///////////////////////////////////////////////////////////////
129    
130      /** Check that a Path belongs to this FileSystem. */
131      @Override
132      protected void checkPath(Path path) {
133        fs.checkPath(path);
134      }
135    
136      @Override
137      public BlockLocation[] getFileBlockLocations(FileStatus file, long start,
138        long len) throws IOException {
139          return fs.getFileBlockLocations(file, start, len);
140      }
141    
142      @Override
143      public Path resolvePath(final Path p) throws IOException {
144        return fs.resolvePath(p);
145      }
146      /**
147       * Opens an FSDataInputStream at the indicated Path.
148       * @param f the file name to open
149       * @param bufferSize the size of the buffer to be used.
150       */
151      @Override
152      public FSDataInputStream open(Path f, int bufferSize) throws IOException {
153        return fs.open(f, bufferSize);
154      }
155    
156      @Override
157      public FSDataOutputStream append(Path f, int bufferSize,
158          Progressable progress) throws IOException {
159        return fs.append(f, bufferSize, progress);
160      }
161    
162      @Override
163      public FSDataOutputStream create(Path f, FsPermission permission,
164          boolean overwrite, int bufferSize, short replication, long blockSize,
165          Progressable progress) throws IOException {
166        return fs.create(f, permission,
167            overwrite, bufferSize, replication, blockSize, progress);
168      }
169    
170      /**
171       * Set replication for an existing file.
172       * 
173       * @param src file name
174       * @param replication new replication
175       * @throws IOException
176       * @return true if successful;
177       *         false if file does not exist or is a directory
178       */
179      @Override
180      public boolean setReplication(Path src, short replication) throws IOException {
181        return fs.setReplication(src, replication);
182      }
183      
184      /**
185       * Renames Path src to Path dst.  Can take place on local fs
186       * or remote DFS.
187       */
188      @Override
189      public boolean rename(Path src, Path dst) throws IOException {
190        return fs.rename(src, dst);
191      }
192      
193      /** Delete a file */
194      @Override
195      public boolean delete(Path f, boolean recursive) throws IOException {
196        return fs.delete(f, recursive);
197      }
198      
199      /** List files in a directory. */
200      @Override
201      public FileStatus[] listStatus(Path f) throws IOException {
202        return fs.listStatus(f);
203      }
204    
205      @Override
206      public RemoteIterator<Path> listCorruptFileBlocks(Path path)
207        throws IOException {
208        return fs.listCorruptFileBlocks(path);
209      }
210    
211      /** List files and its block locations in a directory. */
212      @Override
213      public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f)
214      throws IOException {
215        return fs.listLocatedStatus(f);
216      }
217      
218      @Override
219      public Path getHomeDirectory() {
220        return fs.getHomeDirectory();
221      }
222    
223    
224      /**
225       * Set the current working directory for the given file system. All relative
226       * paths will be resolved relative to it.
227       * 
228       * @param newDir
229       */
230      @Override
231      public void setWorkingDirectory(Path newDir) {
232        fs.setWorkingDirectory(newDir);
233      }
234      
235      /**
236       * Get the current working directory for the given file system
237       * 
238       * @return the directory pathname
239       */
240      @Override
241      public Path getWorkingDirectory() {
242        return fs.getWorkingDirectory();
243      }
244      
245      @Override
246      protected Path getInitialWorkingDirectory() {
247        return fs.getInitialWorkingDirectory();
248      }
249      
250      @Override
251      public FsStatus getStatus(Path p) throws IOException {
252        return fs.getStatus(p);
253      }
254      
255      @Override
256      public boolean mkdirs(Path f, FsPermission permission) throws IOException {
257        return fs.mkdirs(f, permission);
258      }
259    
260    
261      /**
262       * The src file is on the local disk.  Add it to FS at
263       * the given dst name.
264       * delSrc indicates if the source should be removed
265       */
266      @Override
267      public void copyFromLocalFile(boolean delSrc, Path src, Path dst)
268        throws IOException {
269        fs.copyFromLocalFile(delSrc, src, dst);
270      }
271      
272      /**
273       * The src files are on the local disk.  Add it to FS at
274       * the given dst name.
275       * delSrc indicates if the source should be removed
276       */
277      @Override
278      public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
279                                    Path[] srcs, Path dst)
280        throws IOException {
281        fs.copyFromLocalFile(delSrc, overwrite, srcs, dst);
282      }
283      
284      /**
285       * The src file is on the local disk.  Add it to FS at
286       * the given dst name.
287       * delSrc indicates if the source should be removed
288       */
289      @Override
290      public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
291                                    Path src, Path dst)
292        throws IOException {
293        fs.copyFromLocalFile(delSrc, overwrite, src, dst);
294      }
295    
296      /**
297       * The src file is under FS, and the dst is on the local disk.
298       * Copy it from FS control to the local dst name.
299       * delSrc indicates if the src will be removed or not.
300       */   
301      @Override
302      public void copyToLocalFile(boolean delSrc, Path src, Path dst)
303        throws IOException {
304        fs.copyToLocalFile(delSrc, src, dst);
305      }
306      
307      /**
308       * Returns a local File that the user can write output to.  The caller
309       * provides both the eventual FS target name and the local working
310       * file.  If the FS is local, we write directly into the target.  If
311       * the FS is remote, we write into the tmp local area.
312       */
313      @Override
314      public Path startLocalOutput(Path fsOutputFile, Path tmpLocalFile)
315        throws IOException {
316        return fs.startLocalOutput(fsOutputFile, tmpLocalFile);
317      }
318    
319      /**
320       * Called when we're all done writing to the target.  A local FS will
321       * do nothing, because we've written to exactly the right place.  A remote
322       * FS will copy the contents of tmpLocalFile to the correct target at
323       * fsOutputFile.
324       */
325      @Override
326      public void completeLocalOutput(Path fsOutputFile, Path tmpLocalFile)
327        throws IOException {
328        fs.completeLocalOutput(fsOutputFile, tmpLocalFile);
329      }
330    
331      /** Return the total size of all files in the filesystem.*/
332      @Override
333      public long getUsed() throws IOException{
334        return fs.getUsed();
335      }
336      
337      @Override
338      public long getDefaultBlockSize() {
339        return fs.getDefaultBlockSize();
340      }
341      
342      @Override
343      public short getDefaultReplication() {
344        return fs.getDefaultReplication();
345      }
346    
347      @Override
348      public FsServerDefaults getServerDefaults() throws IOException {
349        return fs.getServerDefaults();
350      }
351    
352      // path variants delegate to underlying filesystem 
353      @Override
354      public ContentSummary getContentSummary(Path f) throws IOException {
355        return fs.getContentSummary(f);
356      }
357    
358      @Override
359      public long getDefaultBlockSize(Path f) {
360        return fs.getDefaultBlockSize(f);
361      }
362    
363      @Override
364      public short getDefaultReplication(Path f) {
365        return fs.getDefaultReplication(f);
366      }
367    
368      @Override
369      public FsServerDefaults getServerDefaults(Path f) throws IOException {
370        return fs.getServerDefaults(f);
371      }
372    
373      /**
374       * Get file status.
375       */
376      @Override
377      public FileStatus getFileStatus(Path f) throws IOException {
378        return fs.getFileStatus(f);
379      }
380    
381      @Override
382      public FileChecksum getFileChecksum(Path f) throws IOException {
383        return fs.getFileChecksum(f);
384      }
385      
386      @Override
387      public void setVerifyChecksum(boolean verifyChecksum) {
388        fs.setVerifyChecksum(verifyChecksum);
389      }
390      
391      @Override
392      public void setWriteChecksum(boolean writeChecksum) {
393        fs.setWriteChecksum(writeChecksum);
394      }
395    
396      @Override
397      public Configuration getConf() {
398        return fs.getConf();
399      }
400      
401      @Override
402      public void close() throws IOException {
403        super.close();
404        fs.close();
405      }
406    
407      @Override
408      public void setOwner(Path p, String username, String groupname
409          ) throws IOException {
410        fs.setOwner(p, username, groupname);
411      }
412    
413      @Override
414      public void setTimes(Path p, long mtime, long atime
415          ) throws IOException {
416        fs.setTimes(p, mtime, atime);
417      }
418    
419      @Override
420      public void setPermission(Path p, FsPermission permission
421          ) throws IOException {
422        fs.setPermission(p, permission);
423      }
424    
425      @Override
426      protected FSDataOutputStream primitiveCreate(Path f,
427          FsPermission absolutePermission, EnumSet<CreateFlag> flag,
428          int bufferSize, short replication, long blockSize,
429          Progressable progress, ChecksumOpt checksumOpt)
430          throws IOException {
431        return fs.primitiveCreate(f, absolutePermission, flag,
432            bufferSize, replication, blockSize, progress, checksumOpt);
433      }
434    
435      @Override
436      @SuppressWarnings("deprecation")
437      protected boolean primitiveMkdir(Path f, FsPermission abdolutePermission)
438          throws IOException {
439        return fs.primitiveMkdir(f, abdolutePermission);
440      }
441      
442      @Override // FileSystem
443      public FileSystem[] getChildFileSystems() {
444        return new FileSystem[]{fs};
445      }
446    }