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 }