001 /* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016 package org.opengion.hayabusa.servlet.multipart; 017 018 import java.io.FilterInputStream; 019 import java.io.IOException; 020 import javax.servlet.ServletInputStream; 021 022 /** 023 * ファイルア??ロード時のマルチパート???ファイル読取ストリー?す? 024 * 025 * @og.group そ?他機? 026 * 027 * @version 4.0 028 * @author Kazuhiko Hasegawa 029 * @since JDK5.0, 030 */ 031 public class PartInputStream extends FilterInputStream { 032 private final String boundary; 033 private final byte [] buf = new byte[64*1024]; // 64k 034 private int count; 035 private int pos; 036 private boolean eof; 037 038 /** 039 * 読取ストリー?と区??を?してクラスを構築す?コンストラクター 040 * 041 * @param in ServletInputStreamオブジェク? 042 * @param boundary ??? 043 */ 044 PartInputStream( final ServletInputStream in, 045 final String boundary) throws IOException { 046 super(in); 047 this.boundary = boundary; 048 } 049 050 /** 051 * ??タを埋めます? 052 * 053 * @throws IOException 054 */ 055 private void fill() throws IOException { 056 if(eof) { 057 return; 058 } 059 // as long as we are not just starting up 060 if(count > 0) { 061 // if the caller left the requisite amount spare in the buffer 062 if(count - pos == 2) { 063 // copy it back to the start of the buffer 064 System.arraycopy(buf, pos, buf, 0, count - pos); 065 count -= pos; 066 pos = 0; 067 } else { 068 // should never happen, but just in case 069 throw new IllegalStateException("fill() detected illegal buffer state"); 070 } 071 } 072 073 // try and fill the entire buffer, starting at count, line by line 074 // but never read so close to the end that we might split a boundary 075 int read; 076 int maxRead = buf.length - boundary.length(); 077 while (count < maxRead) { 078 // read a line 079 read = ((ServletInputStream)in).readLine(buf, count, buf.length - count); 080 // check for eof and boundary 081 if(read == -1) { 082 throw new IOException("unexpected end of part"); 083 } else { 084 if(read >= boundary.length()) { 085 eof = true; 086 for(int i=0; i < boundary.length(); i++) { 087 if(boundary.charAt(i) != buf[count + i]) { 088 // Not the boundary! 089 eof = false; 090 break; 091 } 092 } 093 if(eof) { 094 break; 095 } 096 } 097 } 098 // success 099 count += read; 100 } 101 } 102 103 /** 104 * ??タを読み込みます? 105 * 106 * @return 読み取られた??タ 107 * @throws IOException 108 */ 109 @Override 110 public int read() throws IOException { 111 if(count - pos <= 2) { 112 fill(); 113 if(count - pos <= 2) { 114 return -1; 115 } 116 } 117 return buf[pos++] & 0xff; 118 } 119 120 /** 121 * ??タを読み込みます? 122 * 123 * @param bt バイト?? 124 * 125 * @return 読み取られた??タ 126 * @throws IOException 127 */ 128 @Override 129 public int read( final byte[] bt ) throws IOException { 130 return read(bt, 0, bt.length); 131 } 132 133 /** 134 * ??タを読み込みます? 135 * 136 * @param bt バイト?? 137 * @param off 開始バイト数 138 * @param len 読み取りバイト数 139 * 140 * @return 読み取られた??タ 141 * @throws IOException 142 */ 143 @Override 144 public int read( final byte[] bt, final int off, final int len ) throws IOException { 145 int total = 0; 146 if(len == 0) { 147 return 0; 148 } 149 150 int avail = count - pos - 2; 151 if(avail <= 0) { 152 fill(); 153 avail = count - pos - 2; 154 if(avail <= 0) { 155 return -1; 156 } 157 } 158 int copy = Math.min(len, avail); 159 System.arraycopy(buf, pos, bt, off, copy); 160 pos += copy; 161 total += copy; 162 163 while (total < len) { 164 fill(); 165 avail = count - pos - 2; 166 if(avail <= 0) { 167 return total; 168 } 169 copy = Math.min(len - total, avail); 170 System.arraycopy(buf, pos, bt, off + total, copy); 171 pos += copy; 172 total += copy; 173 } 174 return total; 175 } 176 177 /** 178 * 利用可能かど?を返します? 179 * 180 * @return 利用可能かど? 181 * @throws IOException 182 */ 183 @Override 184 public int available() throws IOException { 185 int avail = (count - pos - 2) + in.available(); 186 // Never return a negative value 187 return (avail < 0 ? 0 : avail); 188 } 189 190 /** 191 * 接続を閉じます? 192 * 193 * @throws IOException 194 */ 195 @Override 196 public void close() throws IOException { 197 if(!eof) { 198 int size = read(buf, 0, buf.length); 199 while( size != -1) { 200 size = read(buf, 0, buf.length); 201 } 202 } 203 } 204 }