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