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