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.classification.InterfaceAudience;
022import org.apache.hadoop.fs.FileSystem;
023import org.apache.hadoop.lib.service.FileSystemAccess;
024
025import javax.servlet.Filter;
026import javax.servlet.FilterChain;
027import javax.servlet.FilterConfig;
028import javax.servlet.ServletException;
029import javax.servlet.ServletRequest;
030import javax.servlet.ServletResponse;
031import 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
042public 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}