001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.transfer; 020 021import org.eclipse.aether.RepositoryException; 022 023/** 024 * Thrown in case of a checksum failure during an artifact/metadata download. This exception is usually thrown in 025 * following cases: 026 * <ul> 027 * <li>actual checksum <em>mismatch</em>, see {@link #mismatch(String, String, String)}</li> 028 * <li>lack of required checksums, see {@link #noneAvailable(String, String)}</li> 029 * <li>processing problem during checksum checks (ie IO problem), see {@link #processingFailure(String, Throwable)}</li> 030 * </ul> 031 * It is resolver expectation to provide most available information to caller. 032 */ 033public class ChecksumFailureException extends RepositoryException { 034 035 private final String expected; 036 037 private final String expectedKind; 038 039 private final String actual; 040 041 private final boolean retryWorthy; 042 043 /** 044 * Use in case of checksum mismatch. Creates a new exception with the specified expected, expected kind and actual 045 * checksum. The resulting exception is {@link #isRetryWorthy() retry-worthy}. The checksum match check should 046 * have already happened, this method does not check for any kind of inequality. 047 * 048 * @param expected The expected checksum as declared by the hosting repository, may be {@code null}. 049 * @param expectedKind The expected checksum kind, may be {@code null}. 050 * @param actual The actual checksum as computed from the local bytes, may be {@code null}. 051 * @since 2.0.19 052 */ 053 public static ChecksumFailureException mismatch(String expected, String expectedKind, String actual) { 054 return mismatchDetail(null, expected, expectedKind, actual); 055 } 056 057 /** 058 * Use in case of checksum mismatch. Creates a new exception with the specified expected, expected kind and actual 059 * checksum. The resulting exception is {@link #isRetryWorthy() retry-worthy}. The checksum match check should 060 * have already happened, this method does not check for any kind of inequality. 061 * 062 * @param detail The extra detail/information regarding mismatch. 063 * @param expected The expected checksum as declared by the hosting repository, may be {@code null}. 064 * @param expectedKind The expected checksum kind, may be {@code null}. 065 * @param actual The actual checksum as computed from the local bytes, may be {@code null}. 066 * @since 2.0.19 067 */ 068 public static ChecksumFailureException mismatchDetail( 069 String detail, String expected, String expectedKind, String actual) { 070 String message = "Checksum validation failed, expected '" 071 + expected + "'" + (expectedKind == null ? "" : " (" + expectedKind + ")") 072 + " but is actually '" + actual + "'"; 073 if (detail != null) { 074 message = message + " (" + detail + ")"; 075 } 076 return new ChecksumFailureException(message, null, expected, expectedKind, actual, true); 077 } 078 079 /** 080 * Use in case of checksum not available. Optionally, one can specify which kind was not available. 081 * 082 * @param message The message. 083 * @param expectedKind The expected checksum kind, may be {@code null}. 084 * @since 2.0.19 085 */ 086 public static ChecksumFailureException noneAvailable(String message, String expectedKind) { 087 return new ChecksumFailureException(message, null, "", expectedKind == null ? "" : expectedKind, "", false); 088 } 089 090 /** 091 * Use in case of error, for example IO problem during checksum processing, calculation and alike. Ideally, one 092 * should specify cause as well. 093 * 094 * @param message The message. 095 * @param cause The cause. 096 * @since 2.0.19 097 */ 098 public static ChecksumFailureException processingFailure(String message, Throwable cause) { 099 return new ChecksumFailureException(message, cause, "", "", "", false); 100 } 101 102 /** 103 * Creates a new exception with the specified expected, expected kind and actual checksum. The resulting exception 104 * is {@link #isRetryWorthy() retry-worthy}. 105 * 106 * @param expected The expected checksum as declared by the hosting repository, may be {@code null}. 107 * @param expectedKind The expected checksum kind, may be {@code null}. 108 * @param actual The actual checksum as computed from the local bytes, may be {@code null}. 109 * @since 1.8.0 110 * @deprecated Use {@link #mismatch(String, String, String)} or other suitable helper method instead. 111 */ 112 @Deprecated 113 public ChecksumFailureException(String expected, String expectedKind, String actual) { 114 super("Checksum validation failed, expected '" 115 + expected + "'" + (expectedKind == null ? "" : " (" + expectedKind + ")") 116 + " but is actually '" + actual + "'"); 117 this.expected = expected; 118 this.expectedKind = expectedKind; 119 this.actual = actual; 120 this.retryWorthy = true; 121 } 122 123 /** 124 * Creates a new exception with the specified detail message. The resulting exception is not 125 * {@link #isRetryWorthy() retry-worthy}. Use this constructor ONLY in cases like "no data to work with", 126 * like missing checksums. In every other case use some other constructor. 127 * 128 * @param message The detail message, may be {@code null}. 129 * @deprecated Use {@link #noneAvailable(String, String)} or other suitable helper method instead. 130 */ 131 @Deprecated 132 public ChecksumFailureException(String message) { 133 this(message, null, "", "", "", false); 134 } 135 136 /** 137 * Creates a new exception with the specified cause. The resulting exception is not {@link #isRetryWorthy() 138 * retry-worthy}. Use this constructor in case some other error (ie IO problem) prevented checksum calculation. 139 * 140 * @param cause The exception that caused this one, may be {@code null}. 141 * @deprecated Use {@link #processingFailure(String, Throwable)} or other helper method instead. 142 */ 143 @Deprecated 144 public ChecksumFailureException(Throwable cause) { 145 this("Checksum validation failed" + getMessage(": ", cause), cause, "", "", "", false); 146 } 147 148 /** 149 * Creates a new exception with the specified detail message and cause. The resulting exception is not 150 * {@link #isRetryWorthy() retry-worthy}. Use this constructor in case some other error (ie IO problem) 151 * prevented checksum calculation. 152 * 153 * @param message The detail message, may be {@code null}. 154 * @param cause The exception that caused this one, may be {@code null}. 155 * @deprecated Use {@link #processingFailure(String, Throwable)} or other helper method instead. 156 */ 157 @Deprecated 158 public ChecksumFailureException(String message, Throwable cause) { 159 this(message, cause, "", "", "", false); 160 } 161 162 /** 163 * Creates a new exception with the specified retry flag, detail message and cause. 164 * 165 * @param retryWorthy {@code true} if the exception is retry-worthy, {@code false} otherwise. 166 * @param message The detail message, may be {@code null}. 167 * @param cause The exception that caused this one, may be {@code null}. 168 * @deprecated Do not use this constructor, it lacks information. 169 */ 170 @Deprecated 171 public ChecksumFailureException(boolean retryWorthy, String message, Throwable cause) { 172 this(message, cause, "", "", "", retryWorthy); 173 } 174 175 /** 176 * Hidden constructor, use static helper methods instead, suitable for your case. 177 */ 178 private ChecksumFailureException( 179 String message, Throwable cause, String expected, String expectedKind, String actual, boolean retryWorthy) { 180 super(message, cause); 181 this.expected = expected; 182 this.expectedKind = expectedKind; 183 this.actual = actual; 184 this.retryWorthy = retryWorthy; 185 } 186 187 /** 188 * Gets the expected checksum for the downloaded artifact/metadata. 189 * 190 * @return The expected checksum as declared by the hosting repository or {@code null} if unknown. 191 */ 192 public String getExpected() { 193 return expected; 194 } 195 196 /** 197 * Gets the expected checksum kind for the downloaded artifact/metadata. 198 * 199 * @return The expected checksum kind or {@code null} if unknown. 200 * @since 1.8.0 201 */ 202 public String getExpectedKind() { 203 return expectedKind; 204 } 205 206 /** 207 * Gets the actual checksum for the downloaded artifact/metadata. 208 * 209 * @return The actual checksum as computed from the local bytes or {@code null} if unknown. 210 */ 211 public String getActual() { 212 return actual; 213 } 214 215 /** 216 * Indicates whether the corresponding download is retry-worthy. 217 * 218 * @return {@code true} if retrying the download might solve the checksum failure, {@code false} if the checksum 219 * failure is non-recoverable. 220 */ 221 public boolean isRetryWorthy() { 222 return retryWorthy; 223 } 224}