public void processMessage(final Message message) throws InterruptedException, IOException {

    //noinspection ControlFlowStatementWithoutBraces
    //      if (LOG.isDebugEnabled()) LOG.debug("message: " + message); // NOPMD

    // Set context
    message.setProcessor(this);

    try {

      if (message instanceof Prepareable) {

        // Prepare
        final Prepareable prepareableMessage = (Prepareable) message;

        if (prepareableMessage.isPrepared()) {

          // Validate
          message.validate();

          // Execute
          message.execute();
        } else {

          // Not prepared yet

          final PrepareResult prepareResult = prepareableMessage.prepare();
          prepareableMessage.markPrepared();

          // Process according to prepare results
          if (prepareResult.equals(PrepareResult.EXECUTE)) {

            // Validate
            message.validate();

            // Execute
            message.execute();
          } else if (prepareResult.equals(PrepareResult.BREAK)) {

            //noinspection UnnecessaryReturnStatement
            return; // NOPMD
          } else if (prepareResult.equals(PrepareResult.ROUTE)) {

            route(message);
          } else {
            throw new CacheonixException("Unknown result of prepare: " + prepareResult);
          }
        }

      } else {

        // Validate
        message.validate();

        // Execute
        message.execute();
      }
    } catch (final InvalidMessageException e) {

      LOG.warn("Invalid message: " + e.toString(), e);
      if (message instanceof Request) {

        final Request request = (Request) message;
        if (request.isResponseRequired()) {

          final Response response = request.createResponse(Response.RESULT_ERROR);
          response.setResult(e.toString());
          post(response);
        }
      }
    }
  }