1 36 package org.columba.ristretto.imap; 37 38 import java.io.ByteArrayInputStream ; 39 import java.io.FilterInputStream ; 40 import java.io.IOException ; 41 import java.io.InputStream ; 42 import java.util.LinkedList ; 43 import java.util.regex.Matcher ; 44 import java.util.regex.Pattern ; 45 46 import org.columba.ristretto.concurrency.Mutex; 47 import org.columba.ristretto.imap.parser.IMAPResponseParser; 48 import org.columba.ristretto.imap.parser.MessageAttributeParser; 49 import org.columba.ristretto.io.AsyncInputStream; 50 import org.columba.ristretto.io.ConnectionDroppedException; 51 import org.columba.ristretto.io.TempSourceFactory; 52 import org.columba.ristretto.message.Attributes; 53 import org.columba.ristretto.parser.ParserException; 54 55 62 public class IMAPInputStream extends FilterInputStream { 63 64 private static final Pattern literalPattern = Pattern 65 .compile("\\{(\\d+)\\}$"); 66 67 private IMAPProtocol protocol; 68 69 private Matcher literalMatcher; 70 71 private Mutex mutex; 72 73 private StringBuffer lineBuffer; 74 75 private LinkedList observerList; 76 77 85 public IMAPInputStream(InputStream in, IMAPProtocol protocol) { 86 super(in); 87 literalMatcher = literalPattern.matcher(""); 88 lineBuffer = new StringBuffer (); 89 90 observerList = new LinkedList (); 91 mutex = new Mutex(); 92 93 this.protocol = protocol; 94 } 95 96 106 public InputStream readBodyNonBlocking() throws IOException , IMAPException { 107 mutex.lock(); 108 boolean dontrelease = false; 109 try { 110 IMAPResponse response; 112 try { 113 readLineInBuffer(); 114 response = IMAPResponseParser.parse(lineBuffer); 115 } catch (ParserException e) { 116 throw new IMAPException(e); 117 } 118 119 if (response.isTagged() && (response.isBAD() || response.isNO())) { 121 mutex.release(); 122 throw new IMAPException(response); 123 } 124 125 while (!response.isTagged() 127 && !response.getResponseSubType().equals("FETCH") 128 && response.getResponseMessage().indexOf("BODY") == -1) { 129 protocol.handleResponse(response); 130 131 try { 132 readLineInBuffer(); 133 response = IMAPResponseParser.parse(lineBuffer); 134 } catch (ParserException e) { 135 mutex.release(); 136 throw new IMAPException(e); 137 } 138 } 139 140 if (response.isTagged() && (response.isBAD() || response.isNO())) { 142 mutex.release(); 143 throw new IMAPException(response); 144 } 145 146 literalMatcher.reset(response.getResponseMessage()); 148 149 if (literalMatcher.find()) { 151 152 int size = Integer.parseInt(literalMatcher.group(1)); 154 155 AsyncInputStream result = IMAPDownloadThread.asyncDownload( 156 this, size, mutex); 157 dontrelease = true; 158 return result; 159 } else { 160 Attributes attributes = MessageAttributeParser.parse(response 162 .getResponseMessage()); 163 String body = (String ) attributes.get("BODY"); 164 if (body == null) { 165 mutex.release(); 166 return new ByteArrayInputStream (new byte[0]); 167 } 168 169 if (body.length() > 0 && body.charAt(0) == '\"') { 170 body = body.substring(1, body.length() - 1); 171 } 172 173 try { 174 readLineInBuffer(); 176 } catch (IOException e1) { 177 mutex.release(); 178 throw e1; 179 } 180 181 return new ByteArrayInputStream (body != null ? body 182 .getBytes("US-ASCII") : new byte[0]); 183 } 184 } finally { 185 if (dontrelease == false) { 186 mutex.release(); 187 } 188 } 189 } 190 191 198 public IMAPResponse readResponse() throws IOException , IMAPException { 199 IMAPResponse response; 200 mutex.lock(); 201 try { 202 204 try { 205 readLineInBuffer(); 206 response = IMAPResponseParser.parse(lineBuffer); 207 } catch (ParserException e) { 208 throw new IMAPException(e); 209 } 210 literalMatcher.reset(response.getResponseMessage()); 212 int literalIndex = 0; 213 while (literalMatcher.find()) { 214 int literalSize = Integer.parseInt(literalMatcher.group(1)); 216 217 response.setResponseMessage(response.getResponseMessage() 220 .substring(0, literalMatcher.start()) 221 + '{' + (literalIndex++) + '}'); 222 223 response.addLiteral(TempSourceFactory.createTempSource(this, 225 literalSize)); 226 227 readLineInBuffer(); 229 String restresponse = lineBuffer.toString(); 230 restresponse = restresponse.substring(0, 231 restresponse.length() - 2); 232 response.appendResponseText(restresponse); 233 234 if (restresponse.length() > 3) { 236 literalMatcher.reset(response.getResponseMessage()); 237 } 238 } 239 240 } finally { 241 mutex.release(); 242 } 243 return response; 244 } 245 246 private void readLineInBuffer() throws IOException { 247 lineBuffer.delete(0, lineBuffer.length()); 249 250 int read = in.read(); 251 while (read != '\r' && read != -1) { 253 lineBuffer.append((char) read); 254 read = in.read(); 255 } 256 lineBuffer.append((char) read); 257 258 read = in.read(); 260 if (read != '\n') 261 throw new ConnectionDroppedException(); 262 lineBuffer.append((char) read); 263 } 264 265 273 public boolean hasUnsolicitedReponse() throws IOException { 274 boolean result; 275 276 mutex.lock(); 277 try { 278 result = in.available() > 0; 279 } finally { 280 mutex.release(); 281 } 282 return result; 283 } 284 } 285 | Popular Tags |