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