1 package org.eclipse.aether.transfer; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import java.nio.ByteBuffer; 23 24 import org.eclipse.aether.RepositorySystemSession; 25 26 /** 27 * An event fired to a transfer listener during an artifact/metadata transfer. 28 * 29 * @see TransferListener 30 * @see TransferEvent.Builder 31 */ 32 public final class TransferEvent 33 { 34 35 /** 36 * The type of the event. 37 */ 38 public enum EventType 39 { 40 41 /** 42 * @see TransferListener#transferInitiated(TransferEvent) 43 */ 44 INITIATED, 45 46 /** 47 * @see TransferListener#transferStarted(TransferEvent) 48 */ 49 STARTED, 50 51 /** 52 * @see TransferListener#transferProgressed(TransferEvent) 53 */ 54 PROGRESSED, 55 56 /** 57 * @see TransferListener#transferCorrupted(TransferEvent) 58 */ 59 CORRUPTED, 60 61 /** 62 * @see TransferListener#transferSucceeded(TransferEvent) 63 */ 64 SUCCEEDED, 65 66 /** 67 * @see TransferListener#transferFailed(TransferEvent) 68 */ 69 FAILED 70 71 } 72 73 /** 74 * The type of the request/transfer being performed. 75 */ 76 public enum RequestType 77 { 78 79 /** 80 * Download artifact/metadata. 81 */ 82 GET, 83 84 /** 85 * Check artifact/metadata existence only. 86 */ 87 GET_EXISTENCE, 88 89 /** 90 * Upload artifact/metadata. 91 */ 92 PUT, 93 94 } 95 96 private final EventType type; 97 98 private final RequestType requestType; 99 100 private final RepositorySystemSession session; 101 102 private final TransferResource resource; 103 104 private final ByteBuffer dataBuffer; 105 106 private final long transferredBytes; 107 108 private final Exception exception; 109 110 TransferEvent( Builder builder ) 111 { 112 type = builder.type; 113 requestType = builder.requestType; 114 session = builder.session; 115 resource = builder.resource; 116 dataBuffer = builder.dataBuffer; 117 transferredBytes = builder.transferredBytes; 118 exception = builder.exception; 119 } 120 121 /** 122 * Gets the type of the event. 123 * 124 * @return The type of the event, never {@code null}. 125 */ 126 public EventType getType() 127 { 128 return type; 129 } 130 131 /** 132 * Gets the type of the request/transfer. 133 * 134 * @return The type of the request/transfer, never {@code null}. 135 */ 136 public RequestType getRequestType() 137 { 138 return requestType; 139 } 140 141 /** 142 * Gets the repository system session during which the event occurred. 143 * 144 * @return The repository system session during which the event occurred, never {@code null}. 145 */ 146 public RepositorySystemSession getSession() 147 { 148 return session; 149 } 150 151 /** 152 * Gets the resource that is being transferred. 153 * 154 * @return The resource being transferred, never {@code null}. 155 */ 156 public TransferResource getResource() 157 { 158 return resource; 159 } 160 161 /** 162 * Gets the total number of bytes that have been transferred since the download/upload of the resource was started. 163 * If a download has been resumed, the returned count includes the bytes that were already downloaded during the 164 * previous attempt. In other words, the ratio of transferred bytes to the content length of the resource indicates 165 * the percentage of transfer completion. 166 * 167 * @return The total number of bytes that have been transferred since the transfer started, never negative. 168 * @see #getDataLength() 169 * @see TransferResource#getResumeOffset() 170 */ 171 public long getTransferredBytes() 172 { 173 return transferredBytes; 174 } 175 176 /** 177 * Gets the byte buffer holding the transferred bytes since the last event. A listener must assume this buffer to be 178 * owned by the event source and must not change any byte in this buffer. Also, the buffer is only valid for the 179 * duration of the event callback, i.e. the next event might reuse the same buffer (with updated contents). 180 * Therefore, if the actual event processing is deferred, the byte buffer would have to be cloned to create an 181 * immutable snapshot of its contents. 182 * 183 * @return The (read-only) byte buffer or {@code null} if not applicable to the event, i.e. if the event type is not 184 * {@link EventType#PROGRESSED}. 185 */ 186 public ByteBuffer getDataBuffer() 187 { 188 return ( dataBuffer != null ) ? dataBuffer.asReadOnlyBuffer() : null; 189 } 190 191 /** 192 * Gets the number of bytes that have been transferred since the last event. 193 * 194 * @return The number of bytes that have been transferred since the last event, possibly zero but never negative. 195 * @see #getTransferredBytes() 196 */ 197 public int getDataLength() 198 { 199 return ( dataBuffer != null ) ? dataBuffer.remaining() : 0; 200 } 201 202 /** 203 * Gets the error that occurred during the transfer. 204 * 205 * @return The error that occurred or {@code null} if none. 206 */ 207 public Exception getException() 208 { 209 return exception; 210 } 211 212 @Override 213 public String toString() 214 { 215 return getRequestType() + " " + getType() + " " + getResource(); 216 } 217 218 /** 219 * A builder to create transfer events. 220 */ 221 public static final class Builder 222 { 223 224 EventType type; 225 226 RequestType requestType; 227 228 RepositorySystemSession session; 229 230 TransferResource resource; 231 232 ByteBuffer dataBuffer; 233 234 long transferredBytes; 235 236 Exception exception; 237 238 /** 239 * Creates a new transfer event builder for the specified session and the given resource. 240 * 241 * @param session The repository system session, must not be {@code null}. 242 * @param resource The resource being transferred, must not be {@code null}. 243 */ 244 public Builder( RepositorySystemSession session, TransferResource resource ) 245 { 246 if ( session == null ) 247 { 248 throw new IllegalArgumentException( "session not specified" ); 249 } 250 if ( resource == null ) 251 { 252 throw new IllegalArgumentException( "transfer resource not specified" ); 253 } 254 this.session = session; 255 this.resource = resource; 256 type = EventType.INITIATED; 257 requestType = RequestType.GET; 258 } 259 260 private Builder( Builder prototype ) 261 { 262 session = prototype.session; 263 resource = prototype.resource; 264 type = prototype.type; 265 requestType = prototype.requestType; 266 dataBuffer = prototype.dataBuffer; 267 transferredBytes = prototype.transferredBytes; 268 exception = prototype.exception; 269 } 270 271 /** 272 * Creates a new transfer event builder from the current values of this builder. The state of this builder 273 * remains unchanged. 274 * 275 * @return The new event builder, never {@code null}. 276 */ 277 public Builder copy() 278 { 279 return new Builder( this ); 280 } 281 282 /** 283 * Sets the type of the event and resets event-specific fields. In more detail, the data buffer and the 284 * exception fields are set to {@code null}. Furthermore, the total number of transferred bytes is set to 285 * {@code 0} if the event type is {@link EventType#STARTED}. 286 * 287 * @param type The type of the event, must not be {@code null}. 288 * @return This event builder for chaining, never {@code null}. 289 */ 290 public Builder resetType( EventType type ) 291 { 292 if ( type == null ) 293 { 294 throw new IllegalArgumentException( "event type not specified" ); 295 } 296 this.type = type; 297 dataBuffer = null; 298 exception = null; 299 switch ( type ) 300 { 301 case INITIATED: 302 case STARTED: 303 transferredBytes = 0; 304 default: 305 } 306 return this; 307 } 308 309 /** 310 * Sets the type of the event. When re-using the same builder to generate a sequence of events for one transfer, 311 * {@link #resetType(TransferEvent.EventType)} might be more handy. 312 * 313 * @param type The type of the event, must not be {@code null}. 314 * @return This event builder for chaining, never {@code null}. 315 */ 316 public Builder setType( EventType type ) 317 { 318 if ( type == null ) 319 { 320 throw new IllegalArgumentException( "event type not specified" ); 321 } 322 this.type = type; 323 return this; 324 } 325 326 /** 327 * Sets the type of the request/transfer. 328 * 329 * @param requestType The request/transfer type, must not be {@code null}. 330 * @return This event builder for chaining, never {@code null}. 331 */ 332 public Builder setRequestType( RequestType requestType ) 333 { 334 if ( requestType == null ) 335 { 336 throw new IllegalArgumentException( "request type not specified" ); 337 } 338 this.requestType = requestType; 339 return this; 340 } 341 342 /** 343 * Sets the total number of bytes that have been transferred so far during the download/upload of the resource. 344 * If a download is being resumed, the count must include the bytes that were already downloaded in the previous 345 * attempt and from which the current transfer started. In this case, the event type {@link EventType#STARTED} 346 * should indicate from what byte the download resumes. 347 * 348 * @param transferredBytes The total number of bytes that have been transferred so far during the 349 * download/upload of the resource, must not be negative. 350 * @return This event builder for chaining, never {@code null}. 351 * @see TransferResource#setResumeOffset(long) 352 */ 353 public Builder setTransferredBytes( long transferredBytes ) 354 { 355 if ( transferredBytes < 0 ) 356 { 357 throw new IllegalArgumentException( "number of transferred bytes cannot be negative" ); 358 } 359 this.transferredBytes = transferredBytes; 360 return this; 361 } 362 363 /** 364 * Increments the total number of bytes that have been transferred so far during the download/upload. 365 * 366 * @param transferredBytes The number of bytes that have been transferred since the last event, must not be 367 * negative. 368 * @return This event builder for chaining, never {@code null}. 369 */ 370 public Builder addTransferredBytes( long transferredBytes ) 371 { 372 if ( transferredBytes < 0 ) 373 { 374 throw new IllegalArgumentException( "number of transferred bytes cannot be negative" ); 375 } 376 this.transferredBytes += transferredBytes; 377 return this; 378 } 379 380 /** 381 * Sets the byte buffer holding the transferred bytes since the last event. 382 * 383 * @param buffer The byte buffer holding the transferred bytes since the last event, may be {@code null} if not 384 * applicable to the event. 385 * @param offset The starting point of valid bytes in the array. 386 * @param length The number of valid bytes, must not be negative. 387 * @return This event builder for chaining, never {@code null}. 388 */ 389 public Builder setDataBuffer( byte[] buffer, int offset, int length ) 390 { 391 return setDataBuffer( ( buffer != null ) ? ByteBuffer.wrap( buffer, offset, length ) : null ); 392 } 393 394 /** 395 * Sets the byte buffer holding the transferred bytes since the last event. 396 * 397 * @param dataBuffer The byte buffer holding the transferred bytes since the last event, may be {@code null} if 398 * not applicable to the event. 399 * @return This event builder for chaining, never {@code null}. 400 */ 401 public Builder setDataBuffer( ByteBuffer dataBuffer ) 402 { 403 this.dataBuffer = dataBuffer; 404 return this; 405 } 406 407 /** 408 * Sets the error that occurred during the transfer. 409 * 410 * @param exception The error that occurred during the transfer, may be {@code null} if none. 411 * @return This event builder for chaining, never {@code null}. 412 */ 413 public Builder setException( Exception exception ) 414 { 415 this.exception = exception; 416 return this; 417 } 418 419 /** 420 * Builds a new transfer event from the current values of this builder. The state of the builder itself remains 421 * unchanged. 422 * 423 * @return The transfer event, never {@code null}. 424 */ 425 public TransferEvent build() 426 { 427 return new TransferEvent( this ); 428 } 429 430 } 431 432 }