View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the License. You may obtain a copy of the License at:
    7    *
    8    *   http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.handler.execution;
    17
    18
    19  import java.util.concurrent.Executor;
    20
    21  import org.jboss.netty.util.ExternalResourceReleasable;
    22  import org.jboss.netty.util.internal.ExecutorUtil;
    23
    24  /**
    25   * A special {@link Executor} which allows to chain a series of
    26   * {@link Executor}s and {@link ChannelEventRunnableFilter}.
    27   */
    28  public class ChainedExecutor implements Executor, ExternalResourceReleasable {
    29
    30      private final Executor cur;
    31      private final Executor next;
    32      private final ChannelEventRunnableFilter filter;
    33
    34      /**
    35       * Create a new {@link ChainedExecutor} which will used the given
    36       * {@link ChannelEventRunnableFilter} to see if the {@link #cur} {@link Executor} should get
    37       * used.  Otherwise it will pass the work to the {@link #next} {@link Executor}
    38       *
    39       * @param filter  the {@link ChannelEventRunnableFilter} which will be used to check if the
    40       *                {@link ChannelEventRunnable} should be passed to the cur or next {@link Executor}
    41       * @param cur     the {@link Executor} to use if the {@link ChannelEventRunnableFilter} match
    42       * @param next    the {@link Executor} to use if the {@link ChannelEventRunnableFilter} does not match
    43       */
    44      public ChainedExecutor(ChannelEventRunnableFilter filter, Executor cur, Executor next) {
    45          if (filter == null) {
    46              throw new NullPointerException("filter");
    47          }
    48          if (cur == null) {
    49              throw new NullPointerException("cur");
    50          }
    51          if (next == null) {
    52              throw new NullPointerException("next");
    53          }
    54
    55          this.filter = filter;
    56          this.cur = cur;
    57          this.next = next;
    58      }
    59
    60      /**
    61       * Execute the passed {@link ChannelEventRunnable} with the current {@link Executor} if the
    62       * {@link ChannelEventRunnableFilter} match.  Otherwise pass it to the next {@link Executor} in
    63       * the chain.
    64       */
    65      public void execute(Runnable command) {
    66          assert command instanceof ChannelEventRunnable;
    67          if (filter.filter((ChannelEventRunnable) command)) {
    68              cur.execute(command);
    69          } else {
    70              next.execute(command);
    71          }
    72      }
    73
    74      public void releaseExternalResources() {
    75          ExecutorUtil.terminate(cur, next);
    76          releaseExternal(cur);
    77          releaseExternal(next);
    78      }
    79
    80
    81      private static void releaseExternal(Executor executor) {
    82          if (executor instanceof ExternalResourceReleasable) {
    83              ((ExternalResourceReleasable) executor).releaseExternalResources();
    84          }
    85      }
    86  }