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.lib.servlet;
020    
021    import org.apache.hadoop.fs.FileSystem;
022    import org.apache.hadoop.lib.service.FileSystemAccess;
023    
024    import javax.servlet.Filter;
025    import javax.servlet.FilterChain;
026    import javax.servlet.FilterConfig;
027    import javax.servlet.ServletException;
028    import javax.servlet.ServletRequest;
029    import javax.servlet.ServletResponse;
030    import java.io.IOException;
031    
032    /**
033     * The <code>FileSystemReleaseFilter</code> releases back to the
034     * {@link FileSystemAccess} service a <code>FileSystem</code> instance.
035     * <p/>
036     * This filter is useful in situations where a servlet request
037     * is streaming out HDFS data and the corresponding filesystem
038     * instance have to be closed after the streaming completes.
039     */
040    public abstract class FileSystemReleaseFilter implements Filter {
041      private static final ThreadLocal<FileSystem> FILE_SYSTEM_TL = new ThreadLocal<FileSystem>();
042    
043      /**
044       * Initializes the filter.
045       * <p/>
046       * This implementation is a NOP.
047       *
048       * @param filterConfig filter configuration.
049       *
050       * @throws ServletException thrown if the filter could not be initialized.
051       */
052      @Override
053      public void init(FilterConfig filterConfig) throws ServletException {
054      }
055    
056      /**
057       * It delegates the incoming request to the <code>FilterChain</code>, and
058       * at its completion (in a finally block) releases the filesystem instance
059       * back to the {@link FileSystemAccess} service.
060       *
061       * @param servletRequest servlet request.
062       * @param servletResponse servlet response.
063       * @param filterChain filter chain.
064       *
065       * @throws IOException thrown if an IO error occurrs.
066       * @throws ServletException thrown if a servet error occurrs.
067       */
068      @Override
069      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
070        throws IOException, ServletException {
071        try {
072          filterChain.doFilter(servletRequest, servletResponse);
073        } finally {
074          FileSystem fs = FILE_SYSTEM_TL.get();
075          if (fs != null) {
076            FILE_SYSTEM_TL.remove();
077            getFileSystemAccess().releaseFileSystem(fs);
078          }
079        }
080      }
081    
082      /**
083       * Destroys the filter.
084       * <p/>
085       * This implementation is a NOP.
086       */
087      @Override
088      public void destroy() {
089      }
090    
091      /**
092       * Static method that sets the <code>FileSystem</code> to release back to
093       * the {@link FileSystemAccess} service on servlet request completion.
094       *
095       * @param fs fileystem instance.
096       */
097      public static void setFileSystem(FileSystem fs) {
098        FILE_SYSTEM_TL.set(fs);
099      }
100    
101      /**
102       * Abstract method to be implemetned by concrete implementations of the
103       * filter that return the {@link FileSystemAccess} service to which the filesystem
104       * will be returned to.
105       *
106       * @return the FileSystemAccess service.
107       */
108      protected abstract FileSystemAccess getFileSystemAccess();
109    
110    }