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-2015 ForgeRock AS.
016 */
017
018package org.opends.server.extensions;
019
020
021
022import java.io.IOException;
023import java.nio.ByteBuffer;
024import java.nio.channels.ByteChannel;
025
026
027
028/**
029 * This class redirects read and write requests either to a child byte channel,
030 * or a byte channel to be redirected to.
031 */
032public class RedirectingByteChannel implements ByteChannel
033{
034  /**
035   * Create an instance of a redirecting byte channel using the specified byte
036   * channel as the child.
037   *
038   * @param bc
039   *          A byte channel to use as the child.
040   * @return A redirecting byte channel.
041   */
042  public static RedirectingByteChannel getRedirectingByteChannel(
043      final ByteChannel bc)
044  {
045    return new RedirectingByteChannel(bc);
046  }
047
048
049
050  private final ByteChannel child;
051  private volatile ByteChannel redirect;
052
053
054
055  private RedirectingByteChannel(final ByteChannel child)
056  {
057    this.child = child;
058  }
059
060
061
062  /** {@inheritDoc} */
063  public void close() throws IOException
064  {
065    final ByteChannel tmp = redirect;
066    if (tmp != null)
067    {
068      tmp.close();
069    }
070    else
071    {
072      child.close();
073    }
074  }
075
076
077
078  /**
079   * Disable redirection.
080   */
081  public final void disable()
082  {
083    redirect = null;
084  }
085
086
087
088  /** {@inheritDoc} */
089  public boolean isOpen()
090  {
091    final ByteChannel tmp = redirect;
092    if (tmp != null)
093    {
094      return tmp.isOpen();
095    }
096    else
097    {
098      return child.isOpen();
099    }
100  }
101
102
103
104  /** {@inheritDoc} */
105  public int read(final ByteBuffer buffer) throws IOException
106  {
107    final ByteChannel tmp = redirect;
108    if (tmp != null)
109    {
110      return tmp.read(buffer);
111    }
112    else
113    {
114      return child.read(buffer);
115    }
116  }
117
118
119
120  /**
121   * Redirects a byte channel to a byte channel associated with the specified
122   * provider.
123   *
124   * @param provider
125   *          The provider to redirect to.
126   */
127  public final void redirect(final ConnectionSecurityProvider provider)
128  {
129    redirect = provider.getChannel();
130  }
131
132
133
134  /** {@inheritDoc} */
135  public int write(final ByteBuffer buffer) throws IOException
136  {
137    final ByteChannel tmp = redirect;
138    if (tmp != null)
139    {
140      return tmp.write(buffer);
141    }
142    else
143    {
144      return child.write(buffer);
145    }
146  }
147}