001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2012-2014 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.ldif;
029
030import java.io.IOException;
031
032import org.forgerock.opendj.ldap.Connection;
033import org.forgerock.opendj.ldap.LdapException;
034import org.forgerock.opendj.ldap.requests.AddRequest;
035import org.forgerock.opendj.ldap.requests.DeleteRequest;
036import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
037import org.forgerock.opendj.ldap.requests.ModifyRequest;
038
039import org.forgerock.util.Reject;
040
041/**
042 * A {@code ConnectionChangeRecordWriter} is a bridge from {@code Connection}s
043 * to {@code ChangeRecordWriter}s. A connection change record writer writes
044 * change records by sending appropriate update requests (Add, Delete, Modify,
045 * or ModifyDN) to an underlying connection.
046 * <p>
047 * All update requests are performed synchronously, blocking until an update
048 * result is received. If an update result indicates that an update request has
049 * failed for some reason then the error result is propagated to the caller
050 * using an {@code LdapException}.
051 * <p>
052 * <b>Note:</b> comments are not supported by connection change record writers.
053 * Attempts to write comments will be ignored.
054 */
055public final class ConnectionChangeRecordWriter implements ChangeRecordWriter {
056    private final Connection connection;
057
058    /**
059     * Creates a new connection change record writer whose destination is the
060     * provided connection.
061     *
062     * @param connection
063     *            The connection to use.
064     * @throws NullPointerException
065     *             If {@code connection} was {@code null}.
066     */
067    public ConnectionChangeRecordWriter(final Connection connection) {
068        Reject.ifNull(connection);
069        this.connection = connection;
070    }
071
072    /**
073     * Closes this connection change record writer, including the underlying
074     * connection. Closing a previously closed change record writer has no
075     * effect.
076     */
077    public void close() {
078        connection.close();
079    }
080
081    /**
082     * Connection change record writers do not require flushing, so this method
083     * has no effect.
084     */
085    public void flush() {
086        // Do nothing.
087    }
088
089    /**
090     * Writes the provided Add request to the underlying connection, blocking
091     * until the request completes.
092     *
093     * @param change
094     *            The {@code AddRequest} to be written.
095     * @return A reference to this connection change record writer.
096     * @throws LdapException
097     *             If the result code indicates that the request failed for some
098     *             reason.
099     * @throws NullPointerException
100     *             If {@code change} was {@code null}.
101     */
102    public ConnectionChangeRecordWriter writeChangeRecord(final AddRequest change) throws LdapException {
103        Reject.ifNull(change);
104        connection.add(change);
105        return this;
106    }
107
108    /**
109     * Writes the provided change record to the underlying connection, blocking
110     * until the request completes.
111     *
112     * @param change
113     *            The change record to be written.
114     * @return A reference to this connection change record writer.
115     * @throws LdapException
116     *             If the result code indicates that the request failed for some
117     *             reason.
118     * @throws NullPointerException
119     *             If {@code change} was {@code null}.
120     */
121    public ConnectionChangeRecordWriter writeChangeRecord(final ChangeRecord change) throws LdapException {
122        Reject.ifNull(change);
123
124        final IOException e = change.accept(ChangeRecordVisitorWriter.getInstance(), this);
125        try {
126            if (e != null) {
127                throw e;
128            }
129        } catch (final LdapException e1) {
130            throw e1;
131        } catch (final IOException e1) {
132            // Should not happen.
133            throw new RuntimeException(e1);
134        }
135        return this;
136    }
137
138    /**
139     * Writes the provided Delete request to the underlying connection, blocking
140     * until the request completes.
141     *
142     * @param change
143     *            The {@code DeleteRequest} to be written.
144     * @return A reference to this connection change record writer.
145     * @throws LdapException
146     *             If the result code indicates that the request failed for some
147     *             reason.
148     * @throws NullPointerException
149     *             If {@code change} was {@code null}.
150     */
151    public ConnectionChangeRecordWriter writeChangeRecord(final DeleteRequest change) throws LdapException {
152        Reject.ifNull(change);
153        connection.delete(change);
154        return this;
155    }
156
157    /**
158     * Writes the provided ModifyDN request to the underlying connection,
159     * blocking until the request completes.
160     *
161     * @param change
162     *            The {@code ModifyDNRequest} to be written.
163     * @return A reference to this connection change record writer.
164     * @throws LdapException
165     *             If the result code indicates that the request failed for some
166     *             reason.
167     * @throws NullPointerException
168     *             If {@code change} was {@code null}.
169     */
170    public ConnectionChangeRecordWriter writeChangeRecord(final ModifyDNRequest change) throws LdapException {
171        Reject.ifNull(change);
172        connection.modifyDN(change);
173        return this;
174    }
175
176    /**
177     * Writes the provided Modify request to the underlying connection, blocking
178     * until the request completes.
179     *
180     * @param change
181     *            The {@code ModifyRequest} to be written.
182     * @return A reference to this connection change record writer.
183     * @throws LdapException
184     *             If the result code indicates that the request failed for some
185     *             reason.
186     * @throws NullPointerException
187     *             If {@code change} was {@code null}.
188     */
189    public ConnectionChangeRecordWriter writeChangeRecord(final ModifyRequest change) throws LdapException {
190        Reject.ifNull(change);
191        connection.modify(change);
192        return this;
193    }
194
195    /**
196     * Connection change record writers do not support comments, so the provided
197     * comment will be ignored.
198     *
199     * @param comment
200     *            The {@code CharSequence} to be written as a comment.
201     * @return A reference to this connection change record writer.
202     * @throws NullPointerException
203     *             If {@code comment} was {@code null}.
204     */
205    public ConnectionChangeRecordWriter writeComment(final CharSequence comment) {
206        Reject.ifNull(comment);
207
208        // Do nothing.
209        return this;
210    }
211
212}