Generic input stream impl on top of ajp
| Method from org.apache.jk.common.JkInputStream Detail: |
public void appendHead(Response res) throws IOException {
if( log.isDebugEnabled() )
log.debug("COMMIT sending headers " + res + " " + res.getMimeHeaders() );
C2BConverter c2b=mc.getConverter();
outputMsg.reset();
outputMsg.appendByte(AjpConstants.JK_AJP13_SEND_HEADERS);
outputMsg.appendInt( res.getStatus() );
String message=res.getMessage();
if( message==null ){
message= HttpMessages.getMessage(res.getStatus());
} else {
message = message.replace('\n", ' ").replace('\r", ' ");
}
tempMB.setString( message );
c2b.convert( tempMB );
outputMsg.appendBytes(tempMB);
// XXX add headers
MimeHeaders headers=res.getMimeHeaders();
String contentType = res.getContentType();
if( contentType != null ) {
headers.setValue("Content-Type").setString(contentType);
}
String contentLanguage = res.getContentLanguage();
if( contentLanguage != null ) {
headers.setValue("Content-Language").setString(contentLanguage);
}
long contentLength = res.getContentLengthLong();
if( contentLength >= 0 ) {
headers.setValue("Content-Length").setLong(contentLength);
}
int numHeaders = headers.size();
outputMsg.appendInt(numHeaders);
for( int i=0; i< numHeaders; i++ ) {
MessageBytes hN=headers.getName(i);
// no header to sc conversion - there's little benefit
// on this direction
c2b.convert ( hN );
outputMsg.appendBytes( hN );
MessageBytes hV=headers.getValue(i);
c2b.convert( hV );
outputMsg.appendBytes( hV );
}
mc.getSource().send( outputMsg, mc );
}
|
public int doRead(ByteChunk responseChunk,
Request req) throws IOException {
if( log.isDebugEnabled())
log.debug( "doRead " + end_of_stream+
" " + responseChunk.getOffset()+ " " + responseChunk.getLength());
if( end_of_stream ) {
return -1;
}
if( isFirst && isReadRequired ) {
// Handle special first-body-chunk, but only if httpd expects it.
if( !receive() ) {
return 0;
}
} else if(isEmpty) {
if ( !refillReadBuffer() ){
return -1;
}
}
ByteChunk bc = bodyBuff.getByteChunk();
responseChunk.setBytes( bc.getBuffer(), bc.getStart(), bc.getLength() );
isEmpty = true;
return responseChunk.getLength();
}
|
public int doWrite(ByteChunk chunk,
Response res) throws IOException {
if (!res.isCommitted()) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeader) and
// set the filters accordingly.
res.sendHeaders();
}
int len=chunk.getLength();
byte buf[]=outputMsg.getBuffer();
// 4 - hardcoded, byte[] marshalling overhead
int chunkSize=buf.length - outputMsg.getHeaderLength() - 4;
int off=0;
while( len > 0 ) {
int thisTime=len;
if( thisTime > chunkSize ) {
thisTime=chunkSize;
}
len-=thisTime;
outputMsg.reset();
outputMsg.appendByte( AjpConstants.JK_AJP13_SEND_BODY_CHUNK);
if( log.isTraceEnabled() )
log.trace("doWrite " + off + " " + thisTime + " " + len );
outputMsg.appendBytes( chunk.getBytes(), chunk.getOffset() + off, thisTime );
off+=thisTime;
mc.getSource().send( outputMsg, mc );
}
return 0;
}
|
public void endMessage() throws IOException {
outputMsg.reset();
outputMsg.appendByte(AjpConstants.JK_AJP13_END_RESPONSE);
outputMsg.appendByte(1);
mc.getSource().send(outputMsg, mc);
mc.getSource().flush(outputMsg, mc);
}
|
public boolean isReadRequired() {
return isReadRequired;
}
Return the flag saying that the server is sending a body |
public boolean receive() throws IOException {
isFirst = false;
bodyMsg.reset();
int err = mc.getSource().receive(bodyMsg, mc);
if( log.isDebugEnabled() )
log.info( "Receiving: getting request body chunk " + err + " " + bodyMsg.getLen() );
if(err < 0) {
throw new IOException();
}
// No data received.
if( bodyMsg.getLen() == 0 ) { // just the header
// Don't mark 'end of stream' for the first chunk.
// end_of_stream = true;
return false;
}
int blen = bodyMsg.peekInt();
if( blen == 0 ) {
return false;
}
if( log.isTraceEnabled() ) {
bodyMsg.dump("Body buffer");
}
bodyMsg.getBytes(bodyBuff);
if( log.isTraceEnabled() )
log.trace( "Data:\n" + bodyBuff);
isEmpty = false;
return true;
}
Receive a chunk of data. Called to implement the
'special' packet in ajp13 and to receive the data
after we send a GET_BODY packet |
public void recycle() {
if(isReadRequired && isFirst) {
// The Servlet never read the request body, so we need to junk it
try {
receive();
} catch(IOException iex) {
log.debug("Error consuming request body",iex);
}
}
end_of_stream = false;
isEmpty = true;
isFirst = true;
isReplay = false;
isReadRequired = false;
bodyBuff.recycle();
tempMB.recycle();
}
Must be called before or after each request |
public void setIsReadRequired(boolean irr) {
isReadRequired = irr;
}
Set the flag saying that the server is sending a body |
public void setReplay(ByteChunk replay) {
isFirst = false;
isEmpty = false;
isReplay = true;
bodyBuff.setBytes(replay.getBytes(), replay.getStart(), replay.getLength());
}
Set the replay buffer for Form auth |