public DefaultChannelPipeline(Channel channel) {
    if (channel == null) {
      throw new NullPointerException("channel");
    }
    this.channel = channel;

    tail = new DefaultChannelHandlerContext(this, null, generateName(TAIL_HANDLER), TAIL_HANDLER);

    HeadHandler headHandler;
    switch (channel.metadata().bufferType()) {
      case BYTE:
        headHandler = new ByteHeadHandler();
        break;
      case MESSAGE:
        headHandler = new MessageHeadHandler();
        break;
      default:
        throw new Error("unknown buffer type: " + channel.metadata().bufferType());
    }

    head =
        new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler, true);

    head.next = tail;
    tail.prev = head;

    unsafe = channel.unsafe();
  }
  /** Returns the {@link String} representation of this pipeline. */
  @Override
  public String toString() {
    StringBuilder buf = new StringBuilder();
    buf.append(getClass().getSimpleName());
    buf.append('{');
    DefaultChannelHandlerContext ctx = head.next;
    for (; ; ) {
      if (ctx == tail) {
        break;
      }

      buf.append('(');
      buf.append(ctx.name());
      buf.append(" = ");
      buf.append(ctx.handler().getClass().getName());
      buf.append(')');

      ctx = ctx.next;
      if (ctx == tail) {
        break;
      }

      buf.append(", ");
    }
    buf.append('}');
    return buf.toString();
  }
  private DefaultChannelHandlerContext remove(
      final DefaultChannelHandlerContext ctx, final boolean forward) {
    assert ctx != head && ctx != tail;

    DefaultChannelHandlerContext context;
    Future<?> future;

    synchronized (this) {
      if (!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) {
        remove0(ctx, forward);
        return ctx;
      } else {
        future =
            ctx.executor()
                .submit(
                    new Runnable() {
                      @Override
                      public void run() {
                        synchronized (DefaultChannelPipeline.this) {
                          remove0(ctx, forward);
                        }
                      }
                    });
        context = ctx;
      }
    }

    // Run the following 'waiting' code outside of the above synchronized block
    // in order to avoid deadlock

    waitForFuture(future);

    return context;
  }
  @Override
  public ChannelPipeline addAfter(
      EventExecutorGroup group, String baseName, final String name, ChannelHandler handler) {
    final DefaultChannelHandlerContext ctx;
    final DefaultChannelHandlerContext newCtx;

    synchronized (this) {
      ctx = getContextOrDie(baseName);
      checkDuplicateName(name);
      newCtx = new DefaultChannelHandlerContext(this, group, name, handler);

      if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
        addAfter0(name, ctx, newCtx);
        return this;
      }
    }

    // Run the following 'waiting' code outside of the above synchronized block
    // in order to avoid deadlock

    newCtx.executeOnEventLoop(
        new Runnable() {
          @Override
          public void run() {
            synchronized (DefaultChannelPipeline.this) {
              checkDuplicateName(name);
              addAfter0(name, ctx, newCtx);
            }
          }
        });

    return this;
  }
 @Override
 public ChannelHandler first() {
   DefaultChannelHandlerContext first = head.next;
   if (first == null) {
     return null;
   }
   return first.handler();
 }
 @Override
 public ChannelHandler last() {
   DefaultChannelHandlerContext last = tail.prev;
   if (last == head) {
     return null;
   }
   return last.handler();
 }
  @Override
  public void fireChannelUnregistered() {
    head.fireChannelUnregistered();

    // Free all buffers if channel is closed and unregistered.
    if (!channel.isOpen()) {
      head.invokeFreeInboundBuffer();
    }
  }
  private void replace0(
      DefaultChannelHandlerContext ctx,
      String newName,
      DefaultChannelHandlerContext newCtx,
      boolean forward) {
    boolean sameName = ctx.name().equals(newName);

    DefaultChannelHandlerContext prev = ctx.prev;
    DefaultChannelHandlerContext next = ctx.next;
    newCtx.prev = prev;
    newCtx.next = next;

    callBeforeRemove(ctx);
    callBeforeAdd(newCtx);

    prev.next = newCtx;
    next.prev = newCtx;

    if (!sameName) {
      name2ctx.remove(ctx.name());
    }
    name2ctx.put(newName, newCtx);

    ChannelPipelineException removeException = null;
    ChannelPipelineException addException = null;
    boolean removed = false;
    try {
      callAfterRemove(ctx, forward);
      removed = true;
    } catch (ChannelPipelineException e) {
      removeException = e;
    }

    boolean added = false;
    try {
      callAfterAdd(newCtx);
      added = true;
    } catch (ChannelPipelineException e) {
      addException = e;
    }

    if (!removed && !added) {
      logger.warn(removeException.getMessage(), removeException);
      logger.warn(addException.getMessage(), addException);
      throw new ChannelPipelineException(
          "Both "
              + ctx.handler().getClass().getName()
              + ".afterRemove() and "
              + newCtx.handler().getClass().getName()
              + ".afterAdd() failed; see logs.");
    } else if (!removed) {
      throw removeException;
    } else if (!added) {
      throw addException;
    }
  }
  private void remove0(DefaultChannelHandlerContext ctx, boolean forward) {
    callBeforeRemove(ctx);

    DefaultChannelHandlerContext prev = ctx.prev;
    DefaultChannelHandlerContext next = ctx.next;
    prev.next = next;
    next.prev = prev;
    name2ctx.remove(ctx.name());

    callAfterRemove(ctx, forward);
  }
Exemplo n.º 10
0
 @Override
 public Map<String, ChannelHandler> toMap() {
   Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
   DefaultChannelHandlerContext ctx = head.next;
   for (; ; ) {
     if (ctx == tail) {
       return map;
     }
     map.put(ctx.name(), ctx.handler());
     ctx = ctx.next;
   }
 }
Exemplo n.º 11
0
 @Override
 public List<String> names() {
   List<String> list = new ArrayList<String>();
   DefaultChannelHandlerContext ctx = head.next;
   for (; ; ) {
     if (ctx == null) {
       return list;
     }
     list.add(ctx.name());
     ctx = ctx.next;
   }
 }
Exemplo n.º 12
0
  private void addBefore0(
      final String name, DefaultChannelHandlerContext ctx, DefaultChannelHandlerContext newCtx) {

    newCtx.prev = ctx.prev;
    newCtx.next = ctx;

    callBeforeAdd(newCtx);

    ctx.prev.next = newCtx;
    ctx.prev = newCtx;
    name2ctx.put(name, newCtx);

    callAfterAdd(newCtx);
  }
Exemplo n.º 13
0
  private void addFirst0(String name, DefaultChannelHandlerContext newCtx) {
    DefaultChannelHandlerContext nextCtx = head.next;
    newCtx.prev = head;
    newCtx.next = nextCtx;

    callBeforeAdd(newCtx);

    head.next = newCtx;
    nextCtx.prev = newCtx;

    name2ctx.put(name, newCtx);

    callAfterAdd(newCtx);
  }
Exemplo n.º 14
0
  private void addLast0(final String name, DefaultChannelHandlerContext newCtx) {
    DefaultChannelHandlerContext prev = tail.prev;
    newCtx.prev = prev;
    newCtx.next = tail;

    callBeforeAdd(newCtx);

    prev.next = newCtx;
    tail.prev = newCtx;

    name2ctx.put(name, newCtx);

    callAfterAdd(newCtx);
  }
Exemplo n.º 15
0
  @Override
  public void fireChannelActive() {
    firedChannelActive = true;
    head.fireChannelActive();

    if (channel.config().isAutoRead()) {
      channel.read();
    }

    if (fireInboundBufferUpdatedOnActivation) {
      fireInboundBufferUpdatedOnActivation = false;
      head.fireInboundBufferUpdated();
    }
  }
Exemplo n.º 16
0
  private void addAfter0(
      final String name, DefaultChannelHandlerContext ctx, DefaultChannelHandlerContext newCtx) {
    checkDuplicateName(name);

    newCtx.prev = ctx;
    newCtx.next = ctx.next;

    callBeforeAdd(newCtx);

    ctx.next.prev = newCtx;
    ctx.next = newCtx;

    name2ctx.put(name, newCtx);

    callAfterAdd(newCtx);
  }
Exemplo n.º 17
0
 @Override
 public void fireInboundBufferSuspended() {
   head.fireInboundBufferSuspended();
   if (channel.config().isAutoRead()) {
     read();
   }
 }
Exemplo n.º 18
0
  @Override
  public ChannelHandlerContext context(Class<? extends ChannelHandler> handlerType) {
    if (handlerType == null) {
      throw new NullPointerException("handlerType");
    }

    DefaultChannelHandlerContext ctx = head.next;
    for (; ; ) {
      if (ctx == null) {
        return null;
      }
      if (handlerType.isAssignableFrom(ctx.handler().getClass())) {
        return ctx;
      }
      ctx = ctx.next;
    }
  }
Exemplo n.º 19
0
 @Override
 public void fireChannelInactive() {
   // Some implementations such as EmbeddedChannel can trigger inboundBufferUpdated()
   // after deactivation, so it's safe not to revert the firedChannelActive flag here.
   // Also, all known transports never get re-activated.
   // firedChannelActive = false;
   head.fireChannelInactive();
 }
Exemplo n.º 20
0
 @Override
 public void fireInboundBufferUpdated() {
   if (!firedChannelActive) {
     fireInboundBufferUpdatedOnActivation = true;
     return;
   }
   head.fireInboundBufferUpdated();
 }
Exemplo n.º 21
0
  @Override
  public ChannelHandlerContext context(ChannelHandler handler) {
    if (handler == null) {
      throw new NullPointerException("handler");
    }

    DefaultChannelHandlerContext ctx = head.next;
    for (; ; ) {

      if (ctx == null) {
        return null;
      }

      if (ctx.handler() == handler) {
        return ctx;
      }

      ctx = ctx.next;
    }
  }
Exemplo n.º 22
0
  private ChannelHandler replace(
      final DefaultChannelHandlerContext ctx,
      final String newName,
      ChannelHandler newHandler,
      final boolean forward) {

    assert ctx != head && ctx != tail;

    Future<?> future;
    synchronized (this) {
      boolean sameName = ctx.name().equals(newName);
      if (!sameName) {
        checkDuplicateName(newName);
      }

      final DefaultChannelHandlerContext newCtx =
          new DefaultChannelHandlerContext(this, ctx.executor, newName, newHandler);

      if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
        replace0(ctx, newName, newCtx, forward);

        return ctx.handler();
      } else {
        future =
            newCtx
                .executor()
                .submit(
                    new Runnable() {
                      @Override
                      public void run() {
                        synchronized (DefaultChannelPipeline.this) {
                          replace0(ctx, newName, newCtx, forward);
                        }
                      }
                    });
      }
    }

    // Run the following 'waiting' code outside of the above synchronized block
    // in order to avoid deadlock

    waitForFuture(future);

    return ctx.handler();
  }
Exemplo n.º 23
0
  private void callAfterRemove(final DefaultChannelHandlerContext ctx, boolean forward) {
    final ChannelHandler handler = ctx.handler();

    // Notify the complete removal.
    try {
      handler.afterRemove(ctx);
    } catch (Throwable t) {
      throw new ChannelPipelineException(
          ctx.handler().getClass().getName() + ".afterRemove() has thrown an exception.", t);
    }

    if (forward) {
      ctx.forwardBufferContent();
    } else {
      ctx.clearBuffer();
    }

    ctx.removed = true;

    // Free all buffers before completing removal.
    if (!channel.isRegistered()) {
      ctx.freeHandlerBuffersAfterRemoval();
    }
  }
Exemplo n.º 24
0
 @Override
 public ChannelFuture close(ChannelPromise promise) {
   return tail.close(promise);
 }
Exemplo n.º 25
0
 @Override
 public ChannelFuture disconnect(ChannelPromise promise) {
   return tail.disconnect(promise);
 }
Exemplo n.º 26
0
 @Override
 public ChannelFuture connect(
     SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
   return tail.connect(remoteAddress, localAddress, promise);
 }
Exemplo n.º 27
0
 @Override
 public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
   return tail.bind(localAddress, promise);
 }
Exemplo n.º 28
0
 @Override
 public ChannelFuture write(Object message) {
   return tail.write(message);
 }
Exemplo n.º 29
0
 @Override
 public ChannelFuture flush() {
   return tail.flush();
 }
Exemplo n.º 30
0
 @Override
 public ChannelFuture deregister() {
   return tail.deregister();
 }