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.james.mpt.helper; 021 022import org.apache.james.mpt.api.Continuation; 023 024import java.io.IOException; 025import java.io.OutputStream; 026import java.nio.ByteBuffer; 027import java.nio.CharBuffer; 028import java.nio.charset.Charset; 029 030public class ByteBufferOutputStream extends OutputStream { 031 032 private final ByteBuffer buffer = ByteBuffer.allocate(160384); 033 private final Charset ascii = Charset.forName("ASCII"); 034 private final Continuation continuation; 035 private boolean matchPlus = false; 036 private boolean matchCR = false; 037 private boolean matchLF = false; 038 039 public ByteBufferOutputStream(Continuation continuation) { 040 this.continuation = continuation; 041 } 042 043 public void write(String message) throws IOException { 044 ascii.newEncoder().encode(CharBuffer.wrap(message), buffer, true); 045 } 046 047 public void write(int b) throws IOException { 048 buffer.put((byte) b); 049 if (b == '\n' && matchPlus && matchCR && matchLF) { 050 matchPlus = false; 051 matchCR = false; 052 matchLF = false; 053 continuation.doContinue(); 054 } else if (b == '\n') { 055 matchLF = true; 056 matchPlus = false; 057 matchCR = false; 058 } else if (b == '+' && matchLF) { 059 matchPlus = true; 060 matchCR = false; 061 } else if (b == '\r' && matchPlus && matchLF) { 062 matchCR = true; 063 } else { 064 matchPlus = false; 065 matchCR = false; 066 matchLF = false; 067 } 068 } 069 070 public String nextLine() throws Exception { 071 buffer.flip(); 072 byte last = 0; 073 while (buffer.hasRemaining()) { 074 byte next = buffer.get(); 075 if (last == '\r' && next == '\n') { 076 break; 077 } 078 last = next; 079 } 080 final ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer(); 081 readOnlyBuffer.flip(); 082 int limit = readOnlyBuffer.limit() - 2; 083 if (limit < 0) { 084 limit = 0; 085 } 086 readOnlyBuffer.limit(limit); 087 String result = ascii.decode(readOnlyBuffer).toString(); 088 buffer.compact(); 089 return result; 090 } 091}