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
019package org.apache.hadoop.lib.servlet;
020
021import org.apache.hadoop.fs.FileSystem;
022import org.apache.hadoop.lib.service.FileSystemAccess;
023
024import javax.servlet.Filter;
025import javax.servlet.FilterChain;
026import javax.servlet.FilterConfig;
027import javax.servlet.ServletException;
028import javax.servlet.ServletRequest;
029import javax.servlet.ServletResponse;
030import 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 */
040public 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}