Beispiel #1
0
 public int available() {
   int available = 0;
   if (state == BYTE_STATE) {
     available = bb.getLength();
   } else if (state == CHAR_STATE) {
     available = cb.getLength();
   }
   if (available == 0) {
     coyoteRequest.action(ActionCode.AVAILABLE, null);
     available = (coyoteRequest.getAvailable() > 0) ? 1 : 0;
   }
   return available;
 }
  public void process(Interest interest) {

    RequestInfo rp = request.getRequestProcessor();
    rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
    error = false;
    // keepAlive = true;
    // setting up the I/O
    // this.interest = interest;
    // outputBuffer.recycle();
    inputBuffer.setInterest(interest);
    inputBuffer.setCCNConnector(endpoint.getCCNConnector());
    outputBuffer.setInterest(interest);
    outputBuffer.setCCNConnector(endpoint.getCCNConnector());
    outputBuffer.setUriHashMap(endpoint.getCCNConnector().getUriHashMap());
    // outputBuffer.setCcnhandle(endpoint.getCcnhandle());
    // step1: parse CCN header
    // step2: put the header content into Request
    // while (!error && !endpoint.isPaused()&&keepAlive) {
    if (!error) {
      rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
      inputBuffer.parseRequet();
      // outputBuffer.setUri(inputBuffer.getOriginalUri());
      outputBuffer.setUri(inputBuffer.getUri());
      outputBuffer.initCCNOutputStream();
      request.setStartTime(System.currentTimeMillis());
      // step3: call service(request,response)
      rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
      try {
        adapter.service(request, response);
        // keepAlive = false;
      } catch (Exception e) {
        // TODO Auto-generated catch block
        error = true;
        e.printStackTrace();
      }

      // step4: Finish the handling of the request
      rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
      inputBuffer.endRequest();
      // step5: next request
      // inputBuffer.nextRequest();
      // outputBuffer.nextRequest();

    }
    rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
    // Recycle
    inputBuffer.recycle();
    outputBuffer.recycle();
    // this.interest = null;

  }
Beispiel #3
0
  @Override
  public void log(org.apache.coyote.Request req, org.apache.coyote.Response res, long time) {

    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request == null) {
      // Create objects
      request = connector.createRequest();
      request.setCoyoteRequest(req);
      response = connector.createResponse();
      response.setCoyoteResponse(res);

      // Link objects
      request.setResponse(response);
      response.setRequest(request);

      // Set as notes
      req.setNote(ADAPTER_NOTES, request);
      res.setNote(ADAPTER_NOTES, response);

      // Set query string encoding
      req.getParameters().setQueryStringEncoding(connector.getURIEncoding());
    }

    try {
      // Log at the lowest level available. logAccess() will be
      // automatically called on parent containers.
      boolean logged = false;
      if (request.mappingData != null) {
        if (request.mappingData.context != null) {
          logged = true;
          ((Context) request.mappingData.context).logAccess(request, response, time, true);
        } else if (request.mappingData.host != null) {
          logged = true;
          ((Host) request.mappingData.host).logAccess(request, response, time, true);
        }
      }
      if (!logged) {
        connector.getService().getContainer().logAccess(request, response, time, true);
      }
    } catch (Throwable t) {
      ExceptionUtils.handleThrowable(t);
      log.warn(sm.getString("coyoteAdapter.accesslogFail"), t);
    } finally {
      request.recycle();
      response.recycle();
    }
  }
Beispiel #4
0
  @Override
  public void checkRecycled(org.apache.coyote.Request req, org.apache.coyote.Response res) {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
    String messageKey = null;
    if (request != null && request.getHost() != null) {
      messageKey = "coyoteAdapter.checkRecycled.request";
    } else if (response != null && response.getContentWritten() != 0) {
      messageKey = "coyoteAdapter.checkRecycled.response";
    }
    if (messageKey != null) {
      // Log this request, as it has probably skipped the access log.
      // The log() method will take care of recycling.
      log(req, res, 0L);

      if (connector.getState().isAvailable()) {
        if (log.isInfoEnabled()) {
          log.info(sm.getString(messageKey), new RecycleRequiredException());
        }
      } else {
        // There may be some aborted requests.
        // When connector shuts down, the request and response will not
        // be reused, so there is no issue to warn about here.
        if (log.isDebugEnabled()) {
          log.debug(sm.getString(messageKey), new RecycleRequiredException());
        }
      }
    }
  }
Beispiel #5
0
  protected void setConverter() throws IOException {

    if (coyoteRequest != null) {
      enc = coyoteRequest.getCharacterEncoding();
    }

    gotEnc = true;
    if (enc == null) {
      enc = DEFAULT_ENCODING;
    }
    conv = encoders.get(enc);
    if (conv == null) {
      if (SecurityUtil.isPackageProtectionEnabled()) {
        try {
          conv =
              AccessController.doPrivileged(
                  new PrivilegedExceptionAction<B2CConverter>() {

                    @Override
                    public B2CConverter run() throws IOException {
                      return new B2CConverter(enc);
                    }
                  });
        } catch (PrivilegedActionException ex) {
          Exception e = ex.getException();
          if (e instanceof IOException) {
            throw (IOException) e;
          }
        }
      } else {
        conv = new B2CConverter(enc);
      }
      encoders.put(enc, conv);
    }
  }
 public AbstractProcessor(AbstractEndpoint<S> endpoint) {
   this.endpoint = endpoint;
   asyncStateMachine = new AsyncStateMachine(this);
   request = new Request();
   response = new Response();
   response.setHook(this);
   request.setResponse(response);
 }
Beispiel #7
0
  private void doConnectorAuthenticationAuthorization(
      org.apache.coyote.Request req, Request request) {
    // Set the remote principal
    String username = req.getRemoteUser().toString();
    if (username != null) {
      if (log.isDebugEnabled()) {
        log.debug(sm.getString("coyoteAdapter.authenticate", username));
      }
      if (req.getRemoteUserNeedsAuthorization()) {
        Authenticator authenticator = request.getContext().getAuthenticator();
        if (authenticator == null) {
          // No security constraints configured for the application so
          // no need to authorize the user. Use the CoyotePrincipal to
          // provide the authenticated user.
          request.setUserPrincipal(new CoyotePrincipal(username));
        } else if (!(authenticator instanceof AuthenticatorBase)) {
          if (log.isDebugEnabled()) {
            log.debug(sm.getString("coyoteAdapter.authorize", username));
          }
          // Custom authenticator that may not trigger authorization.
          // Do the authorization here to make sure it is done.
          request.setUserPrincipal(request.getContext().getRealm().authenticate(username));
        }
        // If the Authenticator is an instance of AuthenticatorBase then
        // it will check req.getRemoteUserNeedsAuthorization() and
        // trigger authorization as necessary. It will also cache the
        // result preventing excessive calls to the Realm.
      } else {
        // The connector isn't configured for authorization. Create a
        // user without any roles using the supplied user name.
        request.setUserPrincipal(new CoyotePrincipal(username));
      }
    }

    // Set the authorization type
    String authtype = req.getAuthType().toString();
    if (authtype != null) {
      request.setAuthType(authtype);
    }
  }
Beispiel #8
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;
  }
Beispiel #9
0
  @Override
  public void errorDispatch(org.apache.coyote.Request req, org.apache.coyote.Response res) {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request != null && request.getMappingData().context != null) {
      ((Context) request.getMappingData().context)
          .logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
    } else {
      log(req, res, System.currentTimeMillis() - req.getStartTime());
    }

    if (request != null) {
      request.recycle();
    }

    if (response != null) {
      response.recycle();
    }

    req.recycle();
    res.recycle();
  }
 protected void unregister(Processor<S> processor) {
   if (getProtocol().getDomain() != null) {
     synchronized (this) {
       try {
         Request r = processor.getRequest();
         if (r == null) {
           // Probably an UpgradeProcessor
           return;
         }
         RequestInfo rp = r.getRequestProcessor();
         rp.setGlobalProcessor(null);
         ObjectName rpName = rp.getRpName();
         if (getLog().isDebugEnabled()) {
           getLog().debug("Unregister " + rpName);
         }
         Registry.getRegistry(null, null).unregisterComponent(rpName);
         rp.setRpName(null);
       } catch (Exception e) {
         getLog().warn("Error unregistering request", e);
       }
     }
   }
 }
Beispiel #11
0
  /** Parse session id in URL. */
  protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {

    // If session tracking via cookies has been disabled for the current
    // context, don't go looking for a session ID in a cookie as a cookie
    // from a parent context with a session ID may be present which would
    // overwrite the valid session ID encoded in the URL
    Context context = (Context) request.getMappingData().context;
    if (context != null
        && !context
            .getServletContext()
            .getEffectiveSessionTrackingModes()
            .contains(SessionTrackingMode.COOKIE)) {
      return;
    }

    // Parse session id from cookies
    Cookies serverCookies = req.getCookies();
    int count = serverCookies.getCookieCount();
    if (count <= 0) {
      return;
    }

    String sessionCookieName = SessionConfig.getSessionCookieName(context);

    for (int i = 0; i < count; i++) {
      ServerCookie scookie = serverCookies.getCookie(i);
      if (scookie.getName().equals(sessionCookieName)) {
        // Override anything requested in the URL
        if (!request.isRequestedSessionIdFromCookie()) {
          // Accept only the first session id cookie
          convertMB(scookie.getValue());
          request.setRequestedSessionId(scookie.getValue().toString());
          request.setRequestedSessionCookie(true);
          request.setRequestedSessionURL(false);
          if (log.isDebugEnabled()) {
            log.debug(" Requested cookie session id is " + request.getRequestedSessionId());
          }
        } else {
          if (!request.isRequestedSessionIdValid()) {
            // Replace the session id until one is valid
            convertMB(scookie.getValue());
            request.setRequestedSessionId(scookie.getValue().toString());
          }
        }
      }
    }
  }
  public CCNProcessor(int headerBufferSize, CCNEndpoint endpoint) {
    // TODO Abnprsuto-generated constructor stub
    this.endpoint = endpoint;
    request = new Request();
    inputBuffer = new InternalCCNInputBuffer(request, headerBufferSize);
    response = new Response();
    response.setHook(this);

    outputBuffer = new InternalCCNOutputBuffer(response, headerBufferSize);
    response.setOutputBuffer(outputBuffer);
    request.setResponse(response);

    // nan initializeFilters();

    // Cause loading of HexUtils
    // nan HexUtils.getDec('0');

  }
Beispiel #13
0
  /**
   * Reads new bytes in the byte chunk.
   *
   * @param cbuf Byte buffer to be written to the response
   * @param off Offset
   * @param len Length
   * @throws IOException An underlying IOException occurred
   */
  @Override
  public int realReadBytes(byte cbuf[], int off, int len) throws IOException {

    if (closed) {
      return -1;
    }
    if (coyoteRequest == null) {
      return -1;
    }

    if (state == INITIAL_STATE) {
      state = BYTE_STATE;
    }

    int result = coyoteRequest.doRead(bb);

    return result;
  }
 /** Read the content length from the request. */
 public void setRequest(Request request) {
   contentLength = request.getContentLengthLong();
   remaining = contentLength;
 }
Beispiel #15
0
  /**
   * Event method.
   *
   * @return false to indicate an error, expected or not
   */
  @Override
  public boolean event(
      org.apache.coyote.Request req, org.apache.coyote.Response res, SocketStatus status) {

    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request.getWrapper() == null) {
      return false;
    }

    boolean error = false;
    boolean read = false;
    try {
      if (status == SocketStatus.OPEN_READ) {
        if (response.isClosed()) {
          // The event has been closed asynchronously, so call end instead of
          // read to cleanup the pipeline
          request.getEvent().setEventType(CometEvent.EventType.END);
          request.getEvent().setEventSubType(null);
        } else {
          try {
            // Fill the read buffer of the servlet layer
            if (request.read()) {
              read = true;
            }
          } catch (IOException e) {
            error = true;
          }
          if (read) {
            request.getEvent().setEventType(CometEvent.EventType.READ);
            request.getEvent().setEventSubType(null);
          } else if (error) {
            request.getEvent().setEventType(CometEvent.EventType.ERROR);
            request.getEvent().setEventSubType(CometEvent.EventSubType.CLIENT_DISCONNECT);
          } else {
            request.getEvent().setEventType(CometEvent.EventType.END);
            request.getEvent().setEventSubType(null);
          }
        }
      } else if (status == SocketStatus.DISCONNECT) {
        request.getEvent().setEventType(CometEvent.EventType.ERROR);
        request.getEvent().setEventSubType(CometEvent.EventSubType.CLIENT_DISCONNECT);
        error = true;
      } else if (status == SocketStatus.ERROR) {
        request.getEvent().setEventType(CometEvent.EventType.ERROR);
        request.getEvent().setEventSubType(CometEvent.EventSubType.IOEXCEPTION);
        error = true;
      } else if (status == SocketStatus.STOP) {
        request.getEvent().setEventType(CometEvent.EventType.END);
        request.getEvent().setEventSubType(CometEvent.EventSubType.SERVER_SHUTDOWN);
      } else if (status == SocketStatus.TIMEOUT) {
        if (response.isClosed()) {
          // The event has been closed asynchronously, so call end instead of
          // read to cleanup the pipeline
          request.getEvent().setEventType(CometEvent.EventType.END);
          request.getEvent().setEventSubType(null);
        } else {
          request.getEvent().setEventType(CometEvent.EventType.ERROR);
          request.getEvent().setEventSubType(CometEvent.EventSubType.TIMEOUT);
        }
      }

      req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());

      // Calling the container
      connector
          .getService()
          .getContainer()
          .getPipeline()
          .getFirst()
          .event(request, response, request.getEvent());

      if (!error
          && !response.isClosed()
          && (request.getAttribute(RequestDispatcher.ERROR_EXCEPTION) != null)) {
        // An unexpected exception occurred while processing the event, so
        // error should be called
        request.getEvent().setEventType(CometEvent.EventType.ERROR);
        request.getEvent().setEventSubType(null);
        error = true;
        connector
            .getService()
            .getContainer()
            .getPipeline()
            .getFirst()
            .event(request, response, request.getEvent());
      }
      if (response.isClosed() || !request.isComet()) {
        if (status == SocketStatus.OPEN_READ
            && request.getEvent().getEventType() != EventType.END) {
          // CometEvent.close was called during an event other than END
          request.getEvent().setEventType(CometEvent.EventType.END);
          request.getEvent().setEventSubType(null);
          error = true;
          connector
              .getService()
              .getContainer()
              .getPipeline()
              .getFirst()
              .event(request, response, request.getEvent());
        }
        res.action(ActionCode.COMET_END, null);
      } else if (!error && read && request.getAvailable()) {
        // If this was a read and not all bytes have been read, or if no data
        // was read from the connector, then it is an error
        request.getEvent().setEventType(CometEvent.EventType.ERROR);
        request.getEvent().setEventSubType(CometEvent.EventSubType.IOEXCEPTION);
        error = true;
        connector
            .getService()
            .getContainer()
            .getPipeline()
            .getFirst()
            .event(request, response, request.getEvent());
      }
      return (!error);
    } catch (Throwable t) {
      ExceptionUtils.handleThrowable(t);
      if (!(t instanceof IOException)) {
        log.error(sm.getString("coyoteAdapter.service"), t);
      }
      error = true;
      return false;
    } finally {
      req.getRequestProcessor().setWorkerThreadName(null);
      // Recycle the wrapper request and response
      if (error || response.isClosed() || !request.isComet()) {
        ((Context) request.getMappingData().context)
            .logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
        request.recycle();
        request.setFilterChain(null);
        response.recycle();
      }
    }
  }
Beispiel #16
0
  /**
   * Extract the path parameters from the request. This assumes parameters are of the form
   * /path;name=value;name2=value2/ etc. Currently only really interested in the session ID that
   * will be in this form. Other parameters can safely be ignored.
   *
   * @param req
   * @param request
   */
  protected void parsePathParameters(org.apache.coyote.Request req, Request request) {

    // Process in bytes (this is default format so this is normally a NO-OP
    req.decodedURI().toBytes();

    ByteChunk uriBC = req.decodedURI().getByteChunk();
    int semicolon = uriBC.indexOf(';', 0);

    // What encoding to use? Some platforms, eg z/os, use a default
    // encoding that doesn't give the expected result so be explicit
    String enc = connector.getURIEncoding();
    if (enc == null) {
      enc = "ISO-8859-1";
    }
    Charset charset = null;
    try {
      charset = B2CConverter.getCharset(enc);
    } catch (UnsupportedEncodingException e1) {
      log.warn(sm.getString("coyoteAdapter.parsePathParam", enc));
    }

    if (log.isDebugEnabled()) {
      log.debug(sm.getString("coyoteAdapter.debug", "uriBC", uriBC.toString()));
      log.debug(sm.getString("coyoteAdapter.debug", "semicolon", String.valueOf(semicolon)));
      log.debug(sm.getString("coyoteAdapter.debug", "enc", enc));
    }

    while (semicolon > -1) {
      // Parse path param, and extract it from the decoded request URI
      int start = uriBC.getStart();
      int end = uriBC.getEnd();

      int pathParamStart = semicolon + 1;
      int pathParamEnd =
          ByteChunk.findBytes(
              uriBC.getBuffer(), start + pathParamStart, end, new byte[] {';', '/'});

      String pv = null;

      if (pathParamEnd >= 0) {
        if (charset != null) {
          pv =
              new String(
                  uriBC.getBuffer(),
                  start + pathParamStart,
                  pathParamEnd - pathParamStart,
                  charset);
        }
        // Extract path param from decoded request URI
        byte[] buf = uriBC.getBuffer();
        for (int i = 0; i < end - start - pathParamEnd; i++) {
          buf[start + semicolon + i] = buf[start + i + pathParamEnd];
        }
        uriBC.setBytes(buf, start, end - start - pathParamEnd + semicolon);
      } else {
        if (charset != null) {
          pv =
              new String(
                  uriBC.getBuffer(),
                  start + pathParamStart,
                  (end - start) - pathParamStart,
                  charset);
        }
        uriBC.setEnd(start + semicolon);
      }

      if (log.isDebugEnabled()) {
        log.debug(
            sm.getString("coyoteAdapter.debug", "pathParamStart", String.valueOf(pathParamStart)));
        log.debug(
            sm.getString("coyoteAdapter.debug", "pathParamEnd", String.valueOf(pathParamEnd)));
        log.debug(sm.getString("coyoteAdapter.debug", "pv", pv));
      }

      if (pv != null) {
        int equals = pv.indexOf('=');
        if (equals > -1) {
          String name = pv.substring(0, equals);
          String value = pv.substring(equals + 1);
          request.addPathParameter(name, value);
          if (log.isDebugEnabled()) {
            log.debug(sm.getString("coyoteAdapter.debug", "equals", String.valueOf(equals)));
            log.debug(sm.getString("coyoteAdapter.debug", "name", name));
            log.debug(sm.getString("coyoteAdapter.debug", "value", value));
          }
        }
      }

      semicolon = uriBC.indexOf(';', semicolon);
    }
  }
Beispiel #17
0
  @Override
  public boolean asyncDispatch(
      org.apache.coyote.Request req, org.apache.coyote.Response res, SocketStatus status)
      throws Exception {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request == null) {
      throw new IllegalStateException("Dispatch may only happen on an existing request.");
    }
    boolean comet = false;
    boolean success = true;
    AsyncContextImpl asyncConImpl = (AsyncContextImpl) request.getAsyncContext();
    req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
    try {
      if (!request.isAsync() && !comet) {
        // Error or timeout - need to tell listeners the request is over
        // Have to test this first since state may change while in this
        // method and this is only required if entering this method in
        // this state
        Context ctxt = (Context) request.getMappingData().context;
        if (ctxt != null) {
          ctxt.fireRequestDestroyEvent(request);
        }
        // Lift any suspension (e.g. if sendError() was used by an async
        // request) to allow the response to be written to the client
        response.setSuspended(false);
      }

      if (status == SocketStatus.TIMEOUT) {
        if (!asyncConImpl.timeout()) {
          asyncConImpl.setErrorState(null, false);
        }
      }
      // Has an error occurred during async processing that needs to be
      // processed by the application's error page mechanism (or Tomcat's
      // if the application doesn't define one)?
      if (!request.isAsyncDispatching() && request.isAsync() && response.isErrorReportRequired()) {
        connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
      }

      if (request.isAsyncDispatching()) {
        connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
        Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        if (t != null) {
          asyncConImpl.setErrorState(t, true);
        }
      }

      if (request.isComet()) {
        if (!response.isClosed() && !response.isError()) {
          if (request.getAvailable()
              || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
            // Invoke a read event right away if there are available bytes
            if (event(req, res, SocketStatus.OPEN_READ)) {
              comet = true;
              res.action(ActionCode.COMET_BEGIN, null);
            }
          } else {
            comet = true;
            res.action(ActionCode.COMET_BEGIN, null);
          }
        } else {
          // Clear the filter chain, as otherwise it will not be reset elsewhere
          // since this is a Comet request
          request.setFilterChain(null);
        }
      }
      if (!request.isAsync() && !comet) {
        request.finishRequest();
        response.finishResponse();
        req.action(ActionCode.POST_REQUEST, null);
        ((Context) request.getMappingData().context)
            .logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
      }

      // Check to see if the processor is in an error state. If it is,
      // bail out now.
      AtomicBoolean error = new AtomicBoolean(false);
      res.action(ActionCode.IS_ERROR, error);
      if (error.get()) {
        success = false;
      }
    } catch (IOException e) {
      success = false;
      // Ignore
    } catch (Throwable t) {
      ExceptionUtils.handleThrowable(t);
      success = false;
      log.error(sm.getString("coyoteAdapter.service"), t);
    } finally {
      req.getRequestProcessor().setWorkerThreadName(null);
      // Recycle the wrapper request and response
      if (!success || (!comet && !request.isAsync())) {
        request.recycle();
        response.recycle();
      } else {
        // Clear converters so that the minimum amount of memory
        // is used by this processor
        request.clearEncoders();
        response.clearEncoders();
      }
    }
    return success;
  }
Beispiel #18
0
  /** Parse additional request parameters. */
  protected boolean postParseRequest(
      org.apache.coyote.Request req,
      Request request,
      org.apache.coyote.Response res,
      Response response)
      throws Exception {

    // XXX the processor may have set a correct scheme and port prior to this point,
    // in ajp13 protocols dont make sense to get the port from the connector...
    // otherwise, use connector configuration
    if (!req.scheme().isNull()) {
      // use processor specified scheme to determine secure state
      request.setSecure(req.scheme().equals("https"));
    } else {
      // use connector scheme and secure configuration, (defaults to
      // "http" and false respectively)
      req.scheme().setString(connector.getScheme());
      request.setSecure(connector.getSecure());
    }

    // FIXME: the code below doesnt belongs to here,
    // this is only have sense
    // in Http11, not in ajp13..
    // At this point the Host header has been processed.
    // Override if the proxyPort/proxyHost are set
    String proxyName = connector.getProxyName();
    int proxyPort = connector.getProxyPort();
    if (proxyPort != 0) {
      req.setServerPort(proxyPort);
    }
    if (proxyName != null) {
      req.serverName().setString(proxyName);
    }

    // Copy the raw URI to the decodedURI
    MessageBytes decodedURI = req.decodedURI();
    decodedURI.duplicate(req.requestURI());

    // Parse the path parameters. This will:
    //   - strip out the path parameters
    //   - convert the decodedURI to bytes
    parsePathParameters(req, request);

    // URI decoding
    // %xx decoding of the URL
    try {
      req.getURLDecoder().convert(decodedURI, false);
    } catch (IOException ioe) {
      res.setStatus(400);
      res.setMessage("Invalid URI: " + ioe.getMessage());
      connector.getService().getContainer().logAccess(request, response, 0, true);
      return false;
    }
    // Normalization
    if (!normalize(req.decodedURI())) {
      res.setStatus(400);
      res.setMessage("Invalid URI");
      connector.getService().getContainer().logAccess(request, response, 0, true);
      return false;
    }
    // Character decoding
    convertURI(decodedURI, request);
    // Check that the URI is still normalized
    if (!checkNormalize(req.decodedURI())) {
      res.setStatus(400);
      res.setMessage("Invalid URI character encoding");
      connector.getService().getContainer().logAccess(request, response, 0, true);
      return false;
    }

    // Request mapping.
    MessageBytes serverName;
    if (connector.getUseIPVHosts()) {
      serverName = req.localName();
      if (serverName.isNull()) {
        // well, they did ask for it
        res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);
      }
    } else {
      serverName = req.serverName();
    }
    if (request.isAsyncStarted()) {
      // TODO SERVLET3 - async
      // reset mapping data, should prolly be done elsewhere
      request.getMappingData().recycle();
    }

    // Version for the second mapping loop and
    // Context that we expect to get for that version
    String version = null;
    Context versionContext = null;
    boolean mapRequired = true;

    while (mapRequired) {
      // This will map the the latest version by default
      connector.getMapper().map(serverName, decodedURI, version, request.getMappingData());
      request.setContext((Context) request.getMappingData().context);
      request.setWrapper((Wrapper) request.getMappingData().wrapper);

      // If there is no context at this point, it is likely no ROOT context
      // has been deployed
      if (request.getContext() == null) {
        res.setStatus(404);
        res.setMessage("Not found");
        // No context, so use host
        Host host = request.getHost();
        // Make sure there is a host (might not be during shutdown)
        if (host != null) {
          host.logAccess(request, response, 0, true);
        }
        return false;
      }

      // Now we have the context, we can parse the session ID from the URL
      // (if any). Need to do this before we redirect in case we need to
      // include the session id in the redirect
      String sessionID;
      if (request
          .getServletContext()
          .getEffectiveSessionTrackingModes()
          .contains(SessionTrackingMode.URL)) {

        // Get the session ID if there was one
        sessionID =
            request.getPathParameter(SessionConfig.getSessionUriParamName(request.getContext()));
        if (sessionID != null) {
          request.setRequestedSessionId(sessionID);
          request.setRequestedSessionURL(true);
        }
      }

      // Look for session ID in cookies and SSL session
      parseSessionCookiesId(req, request);
      parseSessionSslId(request);

      sessionID = request.getRequestedSessionId();

      mapRequired = false;
      if (version != null && request.getContext() == versionContext) {
        // We got the version that we asked for. That is it.
      } else {
        version = null;
        versionContext = null;

        Object[] contexts = request.getMappingData().contexts;
        // Single contextVersion means no need to remap
        // No session ID means no possibility of remap
        if (contexts != null && sessionID != null) {
          // Find the context associated with the session
          for (int i = (contexts.length); i > 0; i--) {
            Context ctxt = (Context) contexts[i - 1];
            if (ctxt.getManager().findSession(sessionID) != null) {
              // We found a context. Is it the one that has
              // already been mapped?
              if (!ctxt.equals(request.getMappingData().context)) {
                // Set version so second time through mapping
                // the correct context is found
                version = ctxt.getWebappVersion();
                versionContext = ctxt;
                // Reset mapping
                request.getMappingData().recycle();
                mapRequired = true;
              }
              break;
            }
          }
        }
      }

      if (!mapRequired && request.getContext().getPaused()) {
        // Found a matching context but it is paused. Mapping data will
        // be wrong since some Wrappers may not be registered at this
        // point.
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          // Should never happen
        }
        // Reset mapping
        request.getMappingData().recycle();
        mapRequired = true;
      }
    }

    // Possible redirect
    MessageBytes redirectPathMB = request.getMappingData().redirectPath;
    if (!redirectPathMB.isNull()) {
      String redirectPath = urlEncoder.encode(redirectPathMB.toString());
      String query = request.getQueryString();
      if (request.isRequestedSessionIdFromURL()) {
        // This is not optimal, but as this is not very common, it
        // shouldn't matter
        redirectPath =
            redirectPath
                + ";"
                + SessionConfig.getSessionUriParamName(request.getContext())
                + "="
                + request.getRequestedSessionId();
      }
      if (query != null) {
        // This is not optimal, but as this is not very common, it
        // shouldn't matter
        redirectPath = redirectPath + "?" + query;
      }
      response.sendRedirect(redirectPath);
      request.getContext().logAccess(request, response, 0, true);
      return false;
    }

    // Filter trace method
    if (!connector.getAllowTrace() && req.method().equalsIgnoreCase("TRACE")) {
      Wrapper wrapper = request.getWrapper();
      String header = null;
      if (wrapper != null) {
        String[] methods = wrapper.getServletMethods();
        if (methods != null) {
          for (int i = 0; i < methods.length; i++) {
            if ("TRACE".equals(methods[i])) {
              continue;
            }
            if (header == null) {
              header = methods[i];
            } else {
              header += ", " + methods[i];
            }
          }
        }
      }
      res.setStatus(405);
      res.addHeader("Allow", header);
      res.setMessage("TRACE method is not allowed");
      request.getContext().logAccess(request, response, 0, true);
      return false;
    }

    doConnectorAuthenticationAuthorization(req, request);

    return true;
  }
Beispiel #19
0
  /** Service method. */
  @Override
  public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
      throws Exception {

    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request == null) {

      // Create objects
      request = connector.createRequest();
      request.setCoyoteRequest(req);
      response = connector.createResponse();
      response.setCoyoteResponse(res);

      // Link objects
      request.setResponse(response);
      response.setRequest(request);

      // Set as notes
      req.setNote(ADAPTER_NOTES, request);
      res.setNote(ADAPTER_NOTES, response);

      // Set query string encoding
      req.getParameters().setQueryStringEncoding(connector.getURIEncoding());
    }

    if (connector.getXpoweredBy()) {
      response.addHeader("X-Powered-By", POWERED_BY);
    }

    boolean comet = false;
    boolean async = false;

    try {

      // Parse and set Catalina and configuration specific
      // request parameters
      req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
      boolean postParseSuccess = postParseRequest(req, request, res, response);
      if (postParseSuccess) {
        // check valves if we support async
        request.setAsyncSupported(
            connector.getService().getContainer().getPipeline().isAsyncSupported());
        // Calling the container
        connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

        if (request.isComet()) {
          if (!response.isClosed() && !response.isError()) {
            if (request.getAvailable()
                || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
              // Invoke a read event right away if there are available bytes
              if (event(req, res, SocketStatus.OPEN_READ)) {
                comet = true;
                res.action(ActionCode.COMET_BEGIN, null);
              }
            } else {
              comet = true;
              res.action(ActionCode.COMET_BEGIN, null);
            }
          } else {
            // Clear the filter chain, as otherwise it will not be reset elsewhere
            // since this is a Comet request
            request.setFilterChain(null);
          }
        }
      }
      AsyncContextImpl asyncConImpl = (AsyncContextImpl) request.getAsyncContext();
      if (asyncConImpl != null) {
        async = true;
      } else if (!comet) {
        request.finishRequest();
        response.finishResponse();
        if (postParseSuccess && request.getMappingData().context != null) {
          // Log only if processing was invoked.
          // If postParseRequest() failed, it has already logged it.
          // If context is null this was the start of a comet request
          // that failed and has already been logged.
          ((Context) request.getMappingData().context)
              .logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
        }
        req.action(ActionCode.POST_REQUEST, null);
      }

    } catch (IOException e) {
      // Ignore
    } finally {
      req.getRequestProcessor().setWorkerThreadName(null);
      AtomicBoolean error = new AtomicBoolean(false);
      res.action(ActionCode.IS_ERROR, error);
      // Recycle the wrapper request and response
      if (!comet && !async || error.get()) {
        request.recycle();
        response.recycle();
      } else {
        // Clear converters so that the minimum amount of memory
        // is used by this processor
        request.clearEncoders();
        response.clearEncoders();
      }
    }
  }