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-2010 Sun Microsystems, Inc. 015 * Portions copyright 2012-2016 ForgeRock AS. 016 */ 017package org.forgerock.opendj.ldif; 018 019import java.io.IOException; 020import java.io.OutputStream; 021import java.io.StringWriter; 022import java.io.Writer; 023import java.util.List; 024 025import org.forgerock.opendj.ldap.Attribute; 026import org.forgerock.opendj.ldap.AttributeDescription; 027import org.forgerock.opendj.ldap.ByteString; 028import org.forgerock.opendj.ldap.DN; 029import org.forgerock.opendj.ldap.Entry; 030import org.forgerock.opendj.ldap.Matcher; 031 032import org.forgerock.util.Reject; 033 034/** 035 * An LDIF entry writer writes attribute value records (entries) using the LDAP 036 * Data Interchange Format (LDIF) to a user defined destination. 037 * 038 * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP Data 039 * Interchange Format (LDIF) - Technical Specification </a> 040 */ 041public final class LDIFEntryWriter extends AbstractLDIFWriter implements EntryWriter { 042 043 /** 044 * Returns the LDIF string representation of the provided entry. 045 * 046 * @param entry 047 * The entry. 048 * @return The LDIF string representation of the provided entry. 049 */ 050 public static String toString(final Entry entry) { 051 final StringWriter writer = new StringWriter(128); 052 try (LDIFEntryWriter ldifWriter = new LDIFEntryWriter(writer)) { 053 ldifWriter.setAddUserFriendlyComments(true).writeEntry(entry); 054 } catch (final IOException e) { 055 // Should never happen. 056 throw new IllegalStateException(e); 057 } 058 return writer.toString(); 059 } 060 061 /** 062 * Creates a new LDIF entry writer which will append lines of LDIF to the 063 * provided list. 064 * 065 * @param ldifLines 066 * The list to which lines of LDIF should be appended. 067 */ 068 public LDIFEntryWriter(final List<String> ldifLines) { 069 super(ldifLines); 070 } 071 072 /** 073 * Creates a new LDIF entry writer whose destination is the provided output 074 * stream. 075 * 076 * @param out 077 * The output stream to use. 078 */ 079 public LDIFEntryWriter(final OutputStream out) { 080 super(out); 081 } 082 083 /** 084 * Creates a new LDIF entry writer whose destination is the provided 085 * character stream writer. 086 * 087 * @param writer 088 * The character stream writer to use. 089 */ 090 public LDIFEntryWriter(final Writer writer) { 091 super(writer); 092 } 093 094 @Override 095 public void close() throws IOException { 096 close0(); 097 } 098 099 @Override 100 public void flush() throws IOException { 101 flush0(); 102 } 103 104 /** 105 * Specifies whether user-friendly comments should be added whenever 106 * distinguished names or UTF-8 attribute values are encountered which 107 * contained non-ASCII characters. The default is {@code false}. 108 * 109 * @param addUserFriendlyComments 110 * {@code true} if user-friendly comments should be added, or 111 * {@code false} otherwise. 112 * @return A reference to this {@code LDIFEntryWriter}. 113 */ 114 public LDIFEntryWriter setAddUserFriendlyComments(final boolean addUserFriendlyComments) { 115 this.addUserFriendlyComments = addUserFriendlyComments; 116 return this; 117 } 118 119 /** 120 * Specifies whether all operational attributes should be excluded 121 * from any entries that are written to LDIF. The default is {@code false}. 122 * 123 * @param excludeOperationalAttributes 124 * {@code true} if all operational attributes should be excluded, 125 * or {@code false} otherwise. 126 * @return A reference to this {@code LDIFEntryWriter}. 127 */ 128 public LDIFEntryWriter setExcludeAllOperationalAttributes( 129 final boolean excludeOperationalAttributes) { 130 this.excludeOperationalAttributes = excludeOperationalAttributes; 131 return this; 132 } 133 134 /** 135 * Specifies whether all user attributes should be excluded from any 136 * entries that are written to LDIF. The default is {@code false}. 137 * 138 * @param excludeUserAttributes 139 * {@code true} if all user attributes should be excluded, or 140 * {@code false} otherwise. 141 * @return A reference to this {@code LDIFEntryWriter}. 142 */ 143 public LDIFEntryWriter setExcludeAllUserAttributes(final boolean excludeUserAttributes) { 144 this.excludeUserAttributes = excludeUserAttributes; 145 return this; 146 } 147 148 /** 149 * Excludes the named attribute from any entries that are written to LDIF. 150 * By default all attributes are included unless explicitly excluded. 151 * 152 * @param attributeDescription 153 * The name of the attribute to be excluded. 154 * @return A reference to this {@code LDIFEntryWriter}. 155 */ 156 public LDIFEntryWriter setExcludeAttribute(final AttributeDescription attributeDescription) { 157 Reject.ifNull(attributeDescription); 158 excludeAttributes.add(attributeDescription); 159 return this; 160 } 161 162 /** 163 * Excludes all entries beneath the named entry (inclusive) from being 164 * written to LDIF. By default all entries are written unless explicitly 165 * excluded or included by branches or filters. 166 * 167 * @param excludeBranch 168 * The distinguished name of the branch to be excluded. 169 * @return A reference to this {@code LDIFEntryWriter}. 170 */ 171 public LDIFEntryWriter setExcludeBranch(final DN excludeBranch) { 172 Reject.ifNull(excludeBranch); 173 excludeBranches.add(excludeBranch); 174 return this; 175 } 176 177 /** 178 * Excludes all entries which match the provided filter matcher from being 179 * written to LDIF. By default all entries are written unless explicitly 180 * excluded or included by branches or filters. 181 * 182 * @param excludeFilter 183 * The filter matcher. 184 * @return A reference to this {@code LDIFEntryWriter}. 185 */ 186 public LDIFEntryWriter setExcludeFilter(final Matcher excludeFilter) { 187 Reject.ifNull(excludeFilter); 188 excludeFilters.add(excludeFilter); 189 return this; 190 } 191 192 /** 193 * Ensures that the named attribute is not excluded from any entries that 194 * are written to LDIF. By default all attributes are included unless 195 * explicitly excluded. 196 * 197 * @param attributeDescription 198 * The name of the attribute to be included. 199 * @return A reference to this {@code LDIFEntryWriter}. 200 */ 201 public LDIFEntryWriter setIncludeAttribute(final AttributeDescription attributeDescription) { 202 Reject.ifNull(attributeDescription); 203 includeAttributes.add(attributeDescription); 204 return this; 205 } 206 207 /** 208 * Ensures that all entries beneath the named entry (inclusive) are written 209 * to LDIF. By default all entries are written unless explicitly excluded or 210 * included by branches or filters. 211 * 212 * @param includeBranch 213 * The distinguished name of the branch to be included. 214 * @return A reference to this {@code LDIFEntryWriter}. 215 */ 216 public LDIFEntryWriter setIncludeBranch(final DN includeBranch) { 217 Reject.ifNull(includeBranch); 218 includeBranches.add(includeBranch); 219 return this; 220 } 221 222 /** 223 * Ensures that all entries which match the provided filter matcher are 224 * written to LDIF. By default all entries are written unless explicitly 225 * excluded or included by branches or filters. 226 * 227 * @param includeFilter 228 * The filter matcher. 229 * @return A reference to this {@code LDIFEntryWriter}. 230 */ 231 public LDIFEntryWriter setIncludeFilter(final Matcher includeFilter) { 232 Reject.ifNull(includeFilter); 233 includeFilters.add(includeFilter); 234 return this; 235 } 236 237 /** 238 * Specifies the column at which long lines should be wrapped. A value less 239 * than or equal to zero (the default) indicates that no wrapping should be 240 * performed. 241 * 242 * @param wrapColumn 243 * The column at which long lines should be wrapped. 244 * @return A reference to this {@code LDIFEntryWriter}. 245 */ 246 public LDIFEntryWriter setWrapColumn(final int wrapColumn) { 247 this.wrapColumn = wrapColumn; 248 return this; 249 } 250 251 @Override 252 public LDIFEntryWriter writeComment(final CharSequence comment) throws IOException { 253 writeComment0(comment); 254 return this; 255 } 256 257 @Override 258 public LDIFEntryWriter writeEntry(final Entry entry) throws IOException { 259 Reject.ifNull(entry); 260 261 // Skip if branch containing the entry is excluded. 262 if (isBranchExcluded(entry.getName())) { 263 return this; 264 } 265 266 // Skip if the entry is excluded by any filters. 267 if (isEntryExcluded(entry)) { 268 return this; 269 } 270 271 writeKeyAndValue("dn", entry.getName().toString()); 272 for (final Attribute attribute : entry.getAllAttributes()) { 273 // Filter the attribute if required. 274 if (isAttributeExcluded(attribute.getAttributeDescription())) { 275 continue; 276 } 277 278 final String attributeDescription = attribute.getAttributeDescriptionAsString(); 279 if (attribute.isEmpty()) { 280 writeKeyAndValue(attributeDescription, ByteString.empty()); 281 } else { 282 for (final ByteString value : attribute) { 283 writeKeyAndValue(attributeDescription, value); 284 } 285 } 286 } 287 288 // Make sure there is a blank line after the entry. 289 impl.println(); 290 291 return this; 292 } 293}