001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2016 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import java.io.IOException;
020import java.nio.ByteBuffer;
021import java.nio.channels.ByteChannel;
022
023/**
024 * This class redirects read and write requests either to a child byte channel,
025 * or a byte channel to be redirected to.
026 */
027public class RedirectingByteChannel implements ByteChannel
028{
029  /**
030   * Create an instance of a redirecting byte channel using the specified byte
031   * channel as the child.
032   *
033   * @param bc
034   *          A byte channel to use as the child.
035   * @return A redirecting byte channel.
036   */
037  public static RedirectingByteChannel getRedirectingByteChannel(
038      final ByteChannel bc)
039  {
040    return new RedirectingByteChannel(bc);
041  }
042
043  private final ByteChannel child;
044  private volatile ByteChannel redirect;
045
046  private RedirectingByteChannel(final ByteChannel child)
047  {
048    this.child = child;
049  }
050
051  @Override
052  public void close() throws IOException
053  {
054    final ByteChannel tmp = redirect;
055    if (tmp != null)
056    {
057      tmp.close();
058    }
059    else
060    {
061      child.close();
062    }
063  }
064
065  /** Disable redirection. */
066  public final void disable()
067  {
068    redirect = null;
069  }
070
071  @Override
072  public boolean isOpen()
073  {
074    final ByteChannel tmp = redirect;
075    if (tmp != null)
076    {
077      return tmp.isOpen();
078    }
079    else
080    {
081      return child.isOpen();
082    }
083  }
084
085  @Override
086  public int read(final ByteBuffer buffer) throws IOException
087  {
088    final ByteChannel tmp = redirect;
089    if (tmp != null)
090    {
091      return tmp.read(buffer);
092    }
093    else
094    {
095      return child.read(buffer);
096    }
097  }
098
099  /**
100   * Redirects a byte channel to a byte channel associated with the specified
101   * provider.
102   *
103   * @param provider
104   *          The provider to redirect to.
105   */
106  public final void redirect(final ConnectionSecurityProvider provider)
107  {
108    redirect = provider.getChannel();
109  }
110
111  @Override
112  public int write(final ByteBuffer buffer) throws IOException
113  {
114    final ByteChannel tmp = redirect;
115    if (tmp != null)
116    {
117      return tmp.write(buffer);
118    }
119    else
120    {
121      return child.write(buffer);
122    }
123  }
124}