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 void concat(Path f, Path[] psrcs) throws IOException {
164        fs.concat(f, psrcs);
165      }
166    
167      @Override
168      public FSDataOutputStream create(Path f, FsPermission permission,
169          boolean overwrite, int bufferSize, short replication, long blockSize,
170          Progressable progress) throws IOException {
171        return fs.create(f, permission,
172            overwrite, bufferSize, replication, blockSize, progress);
173      }
174      
175    
176      
177      @Override
178      @Deprecated
179      public FSDataOutputStream createNonRecursive(Path f, FsPermission permission,
180          EnumSet<CreateFlag> flags, int bufferSize, short replication, long blockSize,
181          Progressable progress) throws IOException {
182        
183        return fs.createNonRecursive(f, permission, flags, bufferSize, replication, blockSize,
184            progress);
185      }
186    
187      /**
188       * Set replication for an existing file.
189       * 
190       * @param src file name
191       * @param replication new replication
192       * @throws IOException
193       * @return true if successful;
194       *         false if file does not exist or is a directory
195       */
196      @Override
197      public boolean setReplication(Path src, short replication) throws IOException {
198        return fs.setReplication(src, replication);
199      }
200      
201      /**
202       * Renames Path src to Path dst.  Can take place on local fs
203       * or remote DFS.
204       */
205      @Override
206      public boolean rename(Path src, Path dst) throws IOException {
207        return fs.rename(src, dst);
208      }
209      
210      /** Delete a file */
211      @Override
212      public boolean delete(Path f, boolean recursive) throws IOException {
213        return fs.delete(f, recursive);
214      }
215      
216      /** List files in a directory. */
217      @Override
218      public FileStatus[] listStatus(Path f) throws IOException {
219        return fs.listStatus(f);
220      }
221    
222      @Override
223      public RemoteIterator<Path> listCorruptFileBlocks(Path path)
224        throws IOException {
225        return fs.listCorruptFileBlocks(path);
226      }
227    
228      /** List files and its block locations in a directory. */
229      @Override
230      public RemoteIterator<LocatedFileStatus> listLocatedStatus(Path f)
231      throws IOException {
232        return fs.listLocatedStatus(f);
233      }
234      
235      @Override
236      public Path getHomeDirectory() {
237        return fs.getHomeDirectory();
238      }
239    
240    
241      /**
242       * Set the current working directory for the given file system. All relative
243       * paths will be resolved relative to it.
244       * 
245       * @param newDir
246       */
247      @Override
248      public void setWorkingDirectory(Path newDir) {
249        fs.setWorkingDirectory(newDir);
250      }
251      
252      /**
253       * Get the current working directory for the given file system
254       * 
255       * @return the directory pathname
256       */
257      @Override
258      public Path getWorkingDirectory() {
259        return fs.getWorkingDirectory();
260      }
261      
262      @Override
263      protected Path getInitialWorkingDirectory() {
264        return fs.getInitialWorkingDirectory();
265      }
266      
267      @Override
268      public FsStatus getStatus(Path p) throws IOException {
269        return fs.getStatus(p);
270      }
271      
272      @Override
273      public boolean mkdirs(Path f, FsPermission permission) throws IOException {
274        return fs.mkdirs(f, permission);
275      }
276    
277    
278      /**
279       * The src file is on the local disk.  Add it to FS at
280       * the given dst name.
281       * delSrc indicates if the source should be removed
282       */
283      @Override
284      public void copyFromLocalFile(boolean delSrc, Path src, Path dst)
285        throws IOException {
286        fs.copyFromLocalFile(delSrc, src, dst);
287      }
288      
289      /**
290       * The src files are on the local disk.  Add it to FS at
291       * the given dst name.
292       * delSrc indicates if the source should be removed
293       */
294      @Override
295      public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
296                                    Path[] srcs, Path dst)
297        throws IOException {
298        fs.copyFromLocalFile(delSrc, overwrite, srcs, dst);
299      }
300      
301      /**
302       * The src file is on the local disk.  Add it to FS at
303       * the given dst name.
304       * delSrc indicates if the source should be removed
305       */
306      @Override
307      public void copyFromLocalFile(boolean delSrc, boolean overwrite, 
308                                    Path src, Path dst)
309        throws IOException {
310        fs.copyFromLocalFile(delSrc, overwrite, src, dst);
311      }
312    
313      /**
314       * The src file is under FS, and the dst is on the local disk.
315       * Copy it from FS control to the local dst name.
316       * delSrc indicates if the src will be removed or not.
317       */   
318      @Override
319      public void copyToLocalFile(boolean delSrc, Path src, Path dst)
320        throws IOException {
321        fs.copyToLocalFile(delSrc, src, dst);
322      }
323      
324      /**
325       * Returns a local File that the user can write output to.  The caller
326       * provides both the eventual FS target name and the local working
327       * file.  If the FS is local, we write directly into the target.  If
328       * the FS is remote, we write into the tmp local area.
329       */
330      @Override
331      public Path startLocalOutput(Path fsOutputFile, Path tmpLocalFile)
332        throws IOException {
333        return fs.startLocalOutput(fsOutputFile, tmpLocalFile);
334      }
335    
336      /**
337       * Called when we're all done writing to the target.  A local FS will
338       * do nothing, because we've written to exactly the right place.  A remote
339       * FS will copy the contents of tmpLocalFile to the correct target at
340       * fsOutputFile.
341       */
342      @Override
343      public void completeLocalOutput(Path fsOutputFile, Path tmpLocalFile)
344        throws IOException {
345        fs.completeLocalOutput(fsOutputFile, tmpLocalFile);
346      }
347    
348      /** Return the total size of all files in the filesystem.*/
349      @Override
350      public long getUsed() throws IOException{
351        return fs.getUsed();
352      }
353      
354      @Override
355      public long getDefaultBlockSize() {
356        return fs.getDefaultBlockSize();
357      }
358      
359      @Override
360      public short getDefaultReplication() {
361        return fs.getDefaultReplication();
362      }
363    
364      @Override
365      public FsServerDefaults getServerDefaults() throws IOException {
366        return fs.getServerDefaults();
367      }
368    
369      // path variants delegate to underlying filesystem 
370      @Override
371      public ContentSummary getContentSummary(Path f) throws IOException {
372        return fs.getContentSummary(f);
373      }
374    
375      @Override
376      public long getDefaultBlockSize(Path f) {
377        return fs.getDefaultBlockSize(f);
378      }
379    
380      @Override
381      public short getDefaultReplication(Path f) {
382        return fs.getDefaultReplication(f);
383      }
384    
385      @Override
386      public FsServerDefaults getServerDefaults(Path f) throws IOException {
387        return fs.getServerDefaults(f);
388      }
389    
390      /**
391       * Get file status.
392       */
393      @Override
394      public FileStatus getFileStatus(Path f) throws IOException {
395        return fs.getFileStatus(f);
396      }
397    
398      @Override
399      public FileChecksum getFileChecksum(Path f) throws IOException {
400        return fs.getFileChecksum(f);
401      }
402      
403      @Override
404      public void setVerifyChecksum(boolean verifyChecksum) {
405        fs.setVerifyChecksum(verifyChecksum);
406      }
407      
408      @Override
409      public void setWriteChecksum(boolean writeChecksum) {
410        fs.setWriteChecksum(writeChecksum);
411      }
412    
413      @Override
414      public Configuration getConf() {
415        return fs.getConf();
416      }
417      
418      @Override
419      public void close() throws IOException {
420        super.close();
421        fs.close();
422      }
423    
424      @Override
425      public void setOwner(Path p, String username, String groupname
426          ) throws IOException {
427        fs.setOwner(p, username, groupname);
428      }
429    
430      @Override
431      public void setTimes(Path p, long mtime, long atime
432          ) throws IOException {
433        fs.setTimes(p, mtime, atime);
434      }
435    
436      @Override
437      public void setPermission(Path p, FsPermission permission
438          ) throws IOException {
439        fs.setPermission(p, permission);
440      }
441    
442      @Override
443      protected FSDataOutputStream primitiveCreate(Path f,
444          FsPermission absolutePermission, EnumSet<CreateFlag> flag,
445          int bufferSize, short replication, long blockSize,
446          Progressable progress, ChecksumOpt checksumOpt)
447          throws IOException {
448        return fs.primitiveCreate(f, absolutePermission, flag,
449            bufferSize, replication, blockSize, progress, checksumOpt);
450      }
451    
452      @Override
453      @SuppressWarnings("deprecation")
454      protected boolean primitiveMkdir(Path f, FsPermission abdolutePermission)
455          throws IOException {
456        return fs.primitiveMkdir(f, abdolutePermission);
457      }
458      
459      @Override // FileSystem
460      public FileSystem[] getChildFileSystems() {
461        return new FileSystem[]{fs};
462      }
463    }