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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.filter.stream; 021 022import java.io.IOException; 023 024import org.apache.mina.core.buffer.IoBuffer; 025import org.apache.mina.core.file.FileRegion; 026 027/** 028 * Filter implementation that converts a {@link FileRegion} to {@link IoBuffer} 029 * objects and writes those buffers to the next filter. When end of the 030 * {@code FileRegion} has been reached this filter will call 031 * {@link org.apache.mina.core.filterchain.IoFilter.NextFilter#messageSent(org.apache.mina.core.session.IoSession, org.apache.mina.core.write.WriteRequest)} using the 032 * original {@link FileRegion} written to the session and notifies 033 * {@link org.apache.mina.core.future.WriteFuture} on the original 034 * {@link org.apache.mina.core.write.WriteRequest}. 035 * <p>Normall {@code FileRegion} objects should be handled by the 036 * {@link org.apache.mina.core.service.IoProcessor} but this is not always possible 037 * if a filter is being used that needs to modify the contents of the file 038 * before sending over the network (i.e. the 039 * {@link org.apache.mina.filter.ssl.SslFilter} or a data compression filter.) 040 * </p> 041 * <p> This filter will ignore written messages which aren't {@link FileRegion} 042 * instances. Such messages will be passed to the next filter directly. 043 * </p> 044 * <p><b>NOTE:</b> this filter does not close the file channel in 045 * {@link FileRegion#getFileChannel()} after the data from the file has been 046 * written. The {@code FileChannel} should be closed in either 047 * {@link org.apache.mina.core.service.IoHandler#messageSent(IoSession,Object)} 048 * or in an {@link org.apache.mina.core.future.IoFutureListener} associated with the 049 * {@code WriteFuture}. 050 * </p> 051 * 052 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 053 * @org.apache.xbean.XBean 054 */ 055public class FileRegionWriteFilter extends AbstractStreamWriteFilter<FileRegion> { 056 057 @Override 058 protected Class<FileRegion> getMessageClass() { 059 return FileRegion.class; 060 } 061 062 @Override 063 protected IoBuffer getNextBuffer(FileRegion fileRegion) throws IOException { 064 // If there are no more bytes to read, return null 065 if (fileRegion.getRemainingBytes() <= 0) { 066 return null; 067 } 068 069 // Allocate the buffer for reading from the file 070 final int bufferSize = (int) Math.min(getWriteBufferSize(), fileRegion.getRemainingBytes()); 071 IoBuffer buffer = IoBuffer.allocate(bufferSize); 072 073 // Read from the file 074 int bytesRead = fileRegion.getFileChannel().read(buffer.buf(), fileRegion.getPosition()); 075 fileRegion.update(bytesRead); 076 077 // return the buffer 078 buffer.flip(); 079 return buffer; 080 } 081 082}