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