001/* 002 * Copyright 2007-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2008-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldif; 037 038 039 040import java.util.ArrayList; 041import java.util.Arrays; 042import java.util.Collections; 043import java.util.List; 044 045import com.unboundid.ldap.sdk.Version; 046import com.unboundid.util.Debug; 047import com.unboundid.util.LDAPSDKException; 048import com.unboundid.util.NotMutable; 049import com.unboundid.util.StaticUtils; 050import com.unboundid.util.ThreadSafety; 051import com.unboundid.util.ThreadSafetyLevel; 052import com.unboundid.util.Validator; 053 054 055 056/** 057 * This class defines an exception that may be thrown if a problem occurs while 058 * attempting to decode data read from an LDIF source. It has a flag to 059 * indicate whether it is possible to try to continue reading additional 060 * information from the LDIF source, and also the approximate line number on 061 * which the problem was encountered. 062 */ 063@NotMutable() 064@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 065public final class LDIFException 066 extends LDAPSDKException 067{ 068 /** 069 * The serial version UID for this serializable class. 070 */ 071 private static final long serialVersionUID = 1665883395956836732L; 072 073 074 075 // Indicates whether it is possible to continue attempting to read from the 076 // LDIF source. 077 private final boolean mayContinueReading; 078 079 // The line number in the LDIF source on which the problem occurred. 080 private final long lineNumber; 081 082 // A list of the lines comprising the LDIF data being parsed, if available. 083 private final List<String> dataLines; 084 085 086 087 /** 088 * Creates a new LDIF exception with the provided information. 089 * 090 * @param message A message explaining the problem that occurred. 091 * It must not be {@code null}. 092 * @param lineNumber The line number in the LDIF source on which the 093 * problem occurred. 094 * @param mayContinueReading Indicates whether it is possible to continue 095 * attempting to read from the LDIF source. 096 */ 097 public LDIFException(final String message, final long lineNumber, 098 final boolean mayContinueReading) 099 { 100 this(message, lineNumber, mayContinueReading, (List<CharSequence>) null, 101 null); 102 } 103 104 105 106 /** 107 * Creates a new LDIF exception with the provided information. 108 * 109 * @param message A message explaining the problem that occurred. 110 * It must not be {@code null}. 111 * @param lineNumber The line number in the LDIF source on which the 112 * problem occurred. 113 * @param mayContinueReading Indicates whether it is possible to continue 114 * attempting to read from the LDIF source. 115 * @param cause The underlying exception that triggered this 116 * exception. 117 */ 118 public LDIFException(final String message, final long lineNumber, 119 final boolean mayContinueReading, final Throwable cause) 120 { 121 this(message, lineNumber, mayContinueReading, (List<CharSequence>) null, 122 cause); 123 } 124 125 126 127 /** 128 * Creates a new LDIF exception with the provided information. 129 * 130 * @param message A message explaining the problem that occurred. 131 * It must not be {@code null}. 132 * @param lineNumber The line number in the LDIF source on which the 133 * problem occurred. 134 * @param mayContinueReading Indicates whether it is possible to continue 135 * attempting to read from the LDIF source. 136 * @param dataLines The lines that comprise the data that could not 137 * be parsed as valid LDIF. It may be 138 * {@code null} if this is not available. 139 * @param cause The underlying exception that triggered this 140 * exception. 141 */ 142 public LDIFException(final String message, final long lineNumber, 143 final boolean mayContinueReading, 144 final CharSequence[] dataLines, final Throwable cause) 145 { 146 this(message, lineNumber, mayContinueReading, 147 (dataLines == null) ? null : Arrays.asList(dataLines), 148 cause); 149 } 150 151 152 153 /** 154 * Creates a new LDIF exception with the provided information. 155 * 156 * @param message A message explaining the problem that occurred. 157 * It must not be {@code null}. 158 * @param lineNumber The line number in the LDIF source on which the 159 * problem occurred. 160 * @param mayContinueReading Indicates whether it is possible to continue 161 * attempting to read from the LDIF source. 162 * @param dataLines The lines that comprise the data that could not 163 * be parsed as valid LDIF. It may be 164 * {@code null} if this is not available. 165 * @param cause The underlying exception that triggered this 166 * exception. 167 */ 168 public LDIFException(final String message, final long lineNumber, 169 final boolean mayContinueReading, 170 final List<? extends CharSequence> dataLines, 171 final Throwable cause) 172 { 173 super(message, cause); 174 175 Validator.ensureNotNull(message); 176 177 this.lineNumber = lineNumber; 178 this.mayContinueReading = mayContinueReading; 179 180 if (dataLines == null) 181 { 182 this.dataLines = null; 183 } 184 else 185 { 186 final ArrayList<String> lineList = new ArrayList<>(dataLines.size()); 187 for (final CharSequence s : dataLines) 188 { 189 lineList.add(s.toString()); 190 } 191 192 this.dataLines = Collections.unmodifiableList(lineList); 193 } 194 } 195 196 197 198 /** 199 * Retrieves the line number on which the problem occurred. 200 * 201 * @return The line number on which the problem occurred. 202 */ 203 public long getLineNumber() 204 { 205 return lineNumber; 206 } 207 208 209 210 /** 211 * Indicates whether it is possible to continue attempting to read from the 212 * LDIF source. 213 * 214 * @return {@code true} if it is possible to continue attempting to read from 215 * the LDIF source, or {@code false} if it is not possible to 216 * continue. 217 */ 218 public boolean mayContinueReading() 219 { 220 return mayContinueReading; 221 } 222 223 224 225 /** 226 * Retrieves the lines comprising the data that could not be parsed as valid 227 * LDIF, if available. 228 * 229 * @return An unmodifiable list of the lines comprising the data that could 230 * not be parsed as valid LDIF, or {@code null} if that is not 231 * available. 232 */ 233 public List<String> getDataLines() 234 { 235 return dataLines; 236 } 237 238 239 240 /** 241 * {@inheritDoc} 242 */ 243 @Override() 244 public void toString(final StringBuilder buffer) 245 { 246 final boolean includeCause = 247 Boolean.getBoolean(Debug.PROPERTY_INCLUDE_CAUSE_IN_EXCEPTION_MESSAGES); 248 final boolean includeStackTrace = Boolean.getBoolean( 249 Debug.PROPERTY_INCLUDE_STACK_TRACE_IN_EXCEPTION_MESSAGES); 250 251 toString(buffer, includeCause, includeStackTrace); 252 } 253 254 255 256 /** 257 * Appends a string representation of this {@code LDIFException} to the 258 * provided buffer. 259 * 260 * @param buffer The buffer to which the information should be 261 * appended. This must not be {@code null}. 262 * @param includeCause Indicates whether to include information about 263 * the cause (if any) in the exception message. 264 * @param includeStackTrace Indicates whether to include a condensed 265 * representation of the stack trace in the 266 * exception message. If a stack trace is 267 * included, then the cause (if any) will 268 * automatically be included, regardless of the 269 * value of the {@code includeCause} argument. 270 */ 271 public void toString(final StringBuilder buffer, final boolean includeCause, 272 final boolean includeStackTrace) 273 { 274 buffer.append("LDIFException(lineNumber="); 275 buffer.append(lineNumber); 276 buffer.append(", mayContinueReading="); 277 buffer.append(mayContinueReading); 278 buffer.append(", message='"); 279 buffer.append(getMessage()); 280 281 if (dataLines != null) 282 { 283 buffer.append("', dataLines='"); 284 for (final CharSequence s : dataLines) 285 { 286 buffer.append(s); 287 buffer.append("{end-of-line}"); 288 } 289 } 290 291 if (includeStackTrace) 292 { 293 buffer.append(", trace='"); 294 StaticUtils.getStackTrace(getStackTrace(), buffer); 295 buffer.append('\''); 296 } 297 298 if (includeCause || includeStackTrace) 299 { 300 final Throwable cause = getCause(); 301 if (cause != null) 302 { 303 buffer.append(", cause="); 304 buffer.append(StaticUtils.getExceptionMessage(cause, true, 305 includeStackTrace)); 306 } 307 } 308 309 final String ldapSDKVersionString = ", ldapSDKVersion=" + 310 Version.NUMERIC_VERSION_STRING + ", revision=" + Version.REVISION_ID; 311 if (buffer.indexOf(ldapSDKVersionString) < 0) 312 { 313 buffer.append(ldapSDKVersionString); 314 } 315 316 buffer.append(')'); 317 } 318 319 320 321 /** 322 * {@inheritDoc} 323 */ 324 @Override() 325 public String getExceptionMessage() 326 { 327 return toString(); 328 } 329 330 331 332 /** 333 * {@inheritDoc} 334 */ 335 @Override() 336 public String getExceptionMessage(final boolean includeCause, 337 final boolean includeStackTrace) 338 { 339 final StringBuilder buffer = new StringBuilder(); 340 toString(buffer, includeCause, includeStackTrace); 341 return buffer.toString(); 342 } 343}