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 = null;
    if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER
        && HttpMessages.isSafeInHttpHeader(res.getMessage())) {
      message = res.getMessage();
    }
    if (message == null) {
      message = HttpMessages.getMessage(res.getStatus());
    }
    if (message == null) {
      // mod_jk + httpd 2.x fails with a null status message - bug 45026
      message = Integer.toString(res.getStatus());
    }
    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
      outputMsg.appendBytes(hN);

      MessageBytes hV = headers.getValue(i);
      outputMsg.appendBytes(hV);
    }
    mc.getSource().send(outputMsg, mc);
  }
Beispiel #2
0
  // -------------------- Jk handler implementation --------------------
  // Jk Handler mehod
  public int invoke(Msg msg, MsgContext ep) throws IOException {
    if (ep.isLogTimeEnabled()) ep.setLong(MsgContext.TIMER_PRE_REQUEST, System.currentTimeMillis());

    Request req = ep.getRequest();
    Response res = req.getResponse();

    if (log.isDebugEnabled())
      log.debug("Invoke " + req + " " + res + " " + req.requestURI().toString());

    res.setNote(epNote, ep);
    ep.setStatus(MsgContext.JK_STATUS_HEAD);
    RequestInfo rp = req.getRequestProcessor();
    rp.setStage(Constants.STAGE_SERVICE);
    try {
      adapter.service(req, res);
    } catch (Exception ex) {
      log.info("Error servicing request " + req, ex);
    }
    if (ep.getStatus() != MsgContext.JK_STATUS_CLOSED) {
      res.finish();
    }

    req.updateCounters();
    req.recycle();
    res.recycle();
    ep.recycle();
    if (ep.getStatus() == MsgContext.JK_STATUS_ERROR) {
      return ERROR;
    }
    ep.setStatus(MsgContext.JK_STATUS_NEW);
    rp.setStage(Constants.STAGE_KEEPALIVE);
    return OK;
  }
  /**
   * Get more request body data from the web server and store it in the internal buffer.
   *
   * @return true if there is more data, false if not.
   */
  private boolean refillReadBuffer() throws IOException {
    // If the server returns an empty packet, assume that that end of
    // the stream has been reached (yuck -- fix protocol??).
    if (isReplay) {
      end_of_stream = true; // we've read everything there is
    }
    if (end_of_stream) {
      if (log.isDebugEnabled()) log.debug("refillReadBuffer: end of stream ");
      return false;
    }

    // Why not use outBuf??
    bodyMsg.reset();
    bodyMsg.appendByte(AjpConstants.JK_AJP13_GET_BODY_CHUNK);
    // Adjust allowed size if packetSize != default (AjpConstants.MAX_PACKET_SIZE)
    bodyMsg.appendInt(AjpConstants.MAX_READ_SIZE + packetSize - AjpConstants.MAX_PACKET_SIZE);

    if (log.isDebugEnabled()) log.debug("refillReadBuffer " + Thread.currentThread());

    mc.getSource().send(bodyMsg, mc);
    mc.getSource().flush(bodyMsg, mc); // Server needs to get it

    // In JNI mode, response will be in bodyMsg. In TCP mode, response need to be
    // read

    boolean moreData = receive();
    if (!moreData) {
      end_of_stream = true;
    }
    return moreData;
  }
  /**
   * 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 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;
  }
  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 int invoke(Msg msg, MsgContext ep) throws IOException {
    int type = msg.peekByte();
    ep.setType(type);

    if (type > handlers.length || handlers[type] == null) {
      if (log.isDebugEnabled()) log.debug("Invalid handler " + type);
      return ERROR;
    }

    if (log.isDebugEnabled()) log.debug("Received " + type + " " + handlers[type].getName());

    JkHandler handler = handlers[type];

    return handler.invoke(msg, ep);
  }