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