1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.core; 17 18 import java.nio.channels.AsynchronousChannelGroup; 19 import java.nio.file.FileAlreadyExistsException; 20 import java.nio.file.Path; 21 import java.util.Objects; 22 import java.util.Optional; 23 import java.util.concurrent.ExecutorService; 24 import software.amazon.awssdk.annotations.SdkPublicApi; 25 import software.amazon.awssdk.core.async.AsyncResponseTransformer; 26 import software.amazon.awssdk.utils.Validate; 27 import software.amazon.awssdk.utils.builder.CopyableBuilder; 28 import software.amazon.awssdk.utils.builder.ToCopyableBuilder; 29 30 /** 31 * Configuration options for {@link AsyncResponseTransformer#toFile(Path, FileTransformerConfiguration)} to configure how the SDK 32 * should write the file and if the SDK should delete the file when an exception occurs. 33 * 34 * @see #builder() 35 * @see FileWriteOption 36 * @see FailureBehavior 37 */ 38 @SdkPublicApi 39 public final class FileTransformerConfiguration implements ToCopyableBuilder<FileTransformerConfiguration.Builder, 40 FileTransformerConfiguration> { 41 private final FileWriteOption fileWriteOption; 42 private final FailureBehavior failureBehavior; 43 private final ExecutorService executorService; 44 FileTransformerConfiguration(DefaultBuilder builder)45 private FileTransformerConfiguration(DefaultBuilder builder) { 46 this.fileWriteOption = Validate.paramNotNull(builder.fileWriteOption, "fileWriteOption"); 47 this.failureBehavior = Validate.paramNotNull(builder.failureBehavior, "failureBehavior"); 48 this.executorService = builder.executorService; 49 } 50 51 /** 52 * The configured {@link FileWriteOption} 53 */ fileWriteOption()54 public FileWriteOption fileWriteOption() { 55 return fileWriteOption; 56 } 57 58 /** 59 * The configured {@link FailureBehavior} 60 */ failureBehavior()61 public FailureBehavior failureBehavior() { 62 return failureBehavior; 63 } 64 65 /** 66 * The configured {@link ExecutorService} the writes should be executed on. 67 * <p> 68 * If not set, the default thread pool defined by the underlying {@link java.nio.file.spi.FileSystemProvider} will be used. 69 * This will typically be the thread pool defined by the {@link AsynchronousChannelGroup}. 70 */ executorService()71 public Optional<ExecutorService> executorService() { 72 return Optional.ofNullable(executorService); 73 } 74 75 /** 76 * Create a {@link Builder}, used to create a {@link FileTransformerConfiguration}. 77 */ builder()78 public static Builder builder() { 79 return new DefaultBuilder(); 80 } 81 82 /** 83 * Returns the default {@link FileTransformerConfiguration} for {@link FileWriteOption#CREATE_NEW} 84 * <p> 85 * Always create a new file. If the file already exists, {@link FileAlreadyExistsException} will be thrown. 86 * In the event of an error, the SDK will attempt to delete the file (whatever has been written to it so far). 87 */ defaultCreateNew()88 public static FileTransformerConfiguration defaultCreateNew() { 89 return builder().fileWriteOption(FileWriteOption.CREATE_NEW) 90 .failureBehavior(FailureBehavior.DELETE) 91 .build(); 92 } 93 94 /** 95 * Returns the default {@link FileTransformerConfiguration} for {@link FileWriteOption#CREATE_OR_REPLACE_EXISTING} 96 * <p> 97 * Create a new file if it doesn't exist, otherwise replace the existing file. 98 * In the event of an error, the SDK will NOT attempt to delete the file, leaving it as-is 99 */ defaultCreateOrReplaceExisting()100 public static FileTransformerConfiguration defaultCreateOrReplaceExisting() { 101 return builder().fileWriteOption(FileWriteOption.CREATE_OR_REPLACE_EXISTING) 102 .failureBehavior(FailureBehavior.LEAVE) 103 .build(); 104 } 105 106 /** 107 * Returns the default {@link FileTransformerConfiguration} for {@link FileWriteOption#CREATE_OR_APPEND_TO_EXISTING} 108 * <p> 109 * Create a new file if it doesn't exist, otherwise append to the existing file. 110 * In the event of an error, the SDK will NOT attempt to delete the file, leaving it as-is 111 */ defaultCreateOrAppend()112 public static FileTransformerConfiguration defaultCreateOrAppend() { 113 return builder().fileWriteOption(FileWriteOption.CREATE_OR_APPEND_TO_EXISTING) 114 .failureBehavior(FailureBehavior.LEAVE) 115 .build(); 116 } 117 118 @Override toBuilder()119 public Builder toBuilder() { 120 return new DefaultBuilder(this); 121 } 122 123 @Override equals(Object o)124 public boolean equals(Object o) { 125 if (this == o) { 126 return true; 127 } 128 if (o == null || getClass() != o.getClass()) { 129 return false; 130 } 131 132 FileTransformerConfiguration that = (FileTransformerConfiguration) o; 133 134 if (fileWriteOption != that.fileWriteOption) { 135 return false; 136 } 137 if (failureBehavior != that.failureBehavior) { 138 return false; 139 } 140 return Objects.equals(executorService, that.executorService); 141 } 142 143 @Override hashCode()144 public int hashCode() { 145 int result = fileWriteOption != null ? fileWriteOption.hashCode() : 0; 146 result = 31 * result + (failureBehavior != null ? failureBehavior.hashCode() : 0); 147 result = 31 * result + (executorService != null ? executorService.hashCode() : 0); 148 return result; 149 } 150 151 /** 152 * Defines how the SDK should write the file 153 */ 154 public enum FileWriteOption { 155 /** 156 * Always create a new file. If the file already exists, {@link FileAlreadyExistsException} will be thrown. 157 */ 158 CREATE_NEW, 159 160 /** 161 * Create a new file if it doesn't exist, otherwise replace the existing file. 162 */ 163 CREATE_OR_REPLACE_EXISTING, 164 165 /** 166 * Create a new file if it doesn't exist, otherwise append to the existing file. 167 */ 168 CREATE_OR_APPEND_TO_EXISTING 169 } 170 171 /** 172 * Defines how the SDK should handle the file if there is an exception 173 */ 174 public enum FailureBehavior { 175 /** 176 * In the event of an error, the SDK will attempt to delete the file and whatever has been written to it so far. 177 */ 178 DELETE, 179 180 /** 181 * In the event of an error, the SDK will NOT attempt to delete the file and leave the file as-is (with whatever has been 182 * written to it so far) 183 */ 184 LEAVE 185 } 186 187 public interface Builder extends CopyableBuilder<Builder, FileTransformerConfiguration> { 188 189 /** 190 * Configures how to write the file 191 * 192 * @param fileWriteOption the file write option 193 * @return This object for method chaining. 194 */ fileWriteOption(FileWriteOption fileWriteOption)195 Builder fileWriteOption(FileWriteOption fileWriteOption); 196 197 /** 198 * Configures the {@link FailureBehavior} in the event of an error 199 * 200 * @param failureBehavior the failure behavior 201 * @return This object for method chaining. 202 */ failureBehavior(FailureBehavior failureBehavior)203 Builder failureBehavior(FailureBehavior failureBehavior); 204 205 /** 206 * Configures the {@link ExecutorService} the writes should be executed on. 207 * 208 * @param executorService the executor service to use, or null if using the default thread pool. 209 * @return This object for method chaining. 210 */ executorService(ExecutorService executorService)211 Builder executorService(ExecutorService executorService); 212 } 213 214 private static final class DefaultBuilder implements Builder { 215 private FileWriteOption fileWriteOption; 216 private FailureBehavior failureBehavior; 217 private ExecutorService executorService; 218 DefaultBuilder()219 private DefaultBuilder() { 220 } 221 DefaultBuilder(FileTransformerConfiguration fileTransformerConfiguration)222 private DefaultBuilder(FileTransformerConfiguration fileTransformerConfiguration) { 223 this.fileWriteOption = fileTransformerConfiguration.fileWriteOption; 224 this.failureBehavior = fileTransformerConfiguration.failureBehavior; 225 this.executorService = fileTransformerConfiguration.executorService; 226 } 227 228 @Override fileWriteOption(FileWriteOption fileWriteOption)229 public Builder fileWriteOption(FileWriteOption fileWriteOption) { 230 this.fileWriteOption = fileWriteOption; 231 return this; 232 } 233 234 @Override failureBehavior(FailureBehavior failureBehavior)235 public Builder failureBehavior(FailureBehavior failureBehavior) { 236 this.failureBehavior = failureBehavior; 237 return this; 238 } 239 240 @Override executorService(ExecutorService executorService)241 public Builder executorService(ExecutorService executorService) { 242 this.executorService = executorService; 243 return this; 244 } 245 246 @Override build()247 public FileTransformerConfiguration build() { 248 return new FileTransformerConfiguration(this); 249 } 250 } 251 252 }