package org.eclipse.aether.spi.connector.transport;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

A task to download a resource from the remote repository.
See Also:
  • get.get(GetTask)
/** * A task to download a resource from the remote repository. * * @see Transporter#get(GetTask) */
public final class GetTask extends TransportTask { private File dataFile; private boolean resume; private ByteArrayOutputStream dataBytes; private Map<String, String> checksums;
Creates a new task for the specified remote resource.
Params:
  • location – The relative location of the resource in the remote repository, must not be null.
/** * Creates a new task for the specified remote resource. * * @param location The relative location of the resource in the remote repository, must not be {@code null}. */
public GetTask( URI location ) { checksums = Collections.emptyMap(); setLocation( location ); }
Opens an output stream to store the downloaded data. Depending on getDataFile(), this stream writes either to a file on disk or a growable buffer in memory. It's the responsibility of the caller to close the provided stream.
Throws:
Returns:The output stream for the data, never null. The stream is unbuffered.
/** * Opens an output stream to store the downloaded data. Depending on {@link #getDataFile()}, this stream writes * either to a file on disk or a growable buffer in memory. It's the responsibility of the caller to close the * provided stream. * * @return The output stream for the data, never {@code null}. The stream is unbuffered. * @throws IOException If the stream could not be opened. */
public OutputStream newOutputStream() throws IOException { return newOutputStream( false ); }
Opens an output stream to store the downloaded data. Depending on getDataFile(), this stream writes either to a file on disk or a growable buffer in memory. It's the responsibility of the caller to close the provided stream.
Params:
  • resume – true if the download resumes from the byte offset given by getResumeOffset(), false if the download starts at the first byte of the resource.
Throws:
Returns:The output stream for the data, never null. The stream is unbuffered.
/** * Opens an output stream to store the downloaded data. Depending on {@link #getDataFile()}, this stream writes * either to a file on disk or a growable buffer in memory. It's the responsibility of the caller to close the * provided stream. * * @param resume {@code true} if the download resumes from the byte offset given by {@link #getResumeOffset()}, * {@code false} if the download starts at the first byte of the resource. * @return The output stream for the data, never {@code null}. The stream is unbuffered. * @throws IOException If the stream could not be opened. */
public OutputStream newOutputStream( boolean resume ) throws IOException { if ( dataFile != null ) { return new FileOutputStream( dataFile, this.resume && resume ); } if ( dataBytes == null ) { dataBytes = new ByteArrayOutputStream( 1024 ); } else if ( !resume ) { dataBytes.reset(); } return dataBytes; }
Gets the file (if any) where the downloaded data should be stored. If the specified file already exists, it will be overwritten.
Returns:The data file or null if the data will be buffered in memory.
/** * Gets the file (if any) where the downloaded data should be stored. If the specified file already exists, it will * be overwritten. * * @return The data file or {@code null} if the data will be buffered in memory. */
public File getDataFile() { return dataFile; }
Sets the file where the downloaded data should be stored. If the specified file already exists, it will be overwritten. Unless the caller can reasonably expect the resource to be small, use of a data file is strongly recommended to avoid exhausting heap memory during the download.
Params:
  • dataFile – The file to store the downloaded data, may be null to store the data in memory.
Returns:This task for chaining, never null.
/** * Sets the file where the downloaded data should be stored. If the specified file already exists, it will be * overwritten. Unless the caller can reasonably expect the resource to be small, use of a data file is strongly * recommended to avoid exhausting heap memory during the download. * * @param dataFile The file to store the downloaded data, may be {@code null} to store the data in memory. * @return This task for chaining, never {@code null}. */
public GetTask setDataFile( File dataFile ) { return setDataFile( dataFile, false ); }
Sets the file where the downloaded data should be stored. If the specified file already exists, it will be overwritten or appended to, depending on the resume argument and the capabilities of the transporter. Unless the caller can reasonably expect the resource to be small, use of a data file is strongly recommended to avoid exhausting heap memory during the download.
Params:
  • dataFile – The file to store the downloaded data, may be null to store the data in memory.
  • resume – true to request resuming a previous download attempt, starting from the current length of the data file, false to download the resource from its beginning.
Returns:This task for chaining, never null.
/** * Sets the file where the downloaded data should be stored. If the specified file already exists, it will be * overwritten or appended to, depending on the {@code resume} argument and the capabilities of the transporter. * Unless the caller can reasonably expect the resource to be small, use of a data file is strongly recommended to * avoid exhausting heap memory during the download. * * @param dataFile The file to store the downloaded data, may be {@code null} to store the data in memory. * @param resume {@code true} to request resuming a previous download attempt, starting from the current length of * the data file, {@code false} to download the resource from its beginning. * @return This task for chaining, never {@code null}. */
public GetTask setDataFile( File dataFile, boolean resume ) { this.dataFile = dataFile; this.resume = resume; return this; }
Gets the byte offset within the resource from which the download should resume if supported.
Returns:The zero-based index of the first byte to download or 0 for a full download from the start of the resource, never negative.
/** * Gets the byte offset within the resource from which the download should resume if supported. * * @return The zero-based index of the first byte to download or {@code 0} for a full download from the start of the * resource, never negative. */
public long getResumeOffset() { if ( resume ) { if ( dataFile != null ) { return dataFile.length(); } if ( dataBytes != null ) { return dataBytes.size(); } } return 0; }
Gets the data that was downloaded into memory. Note: This method may only be called if getDataFile() is null as otherwise the downloaded data has been written directly to disk.
Returns:The possibly empty data bytes, never null.
/** * Gets the data that was downloaded into memory. <strong>Note:</strong> This method may only be called if * {@link #getDataFile()} is {@code null} as otherwise the downloaded data has been written directly to disk. * * @return The possibly empty data bytes, never {@code null}. */
public byte[] getDataBytes() { if ( dataFile != null || dataBytes == null ) { return EMPTY; } return dataBytes.toByteArray(); }
Gets the data that was downloaded into memory as a string. The downloaded data is assumed to be encoded using UTF-8. Note: This method may only be called if getDataFile() is null as otherwise the downloaded data has been written directly to disk.
Returns:The possibly empty data string, never null.
/** * Gets the data that was downloaded into memory as a string. The downloaded data is assumed to be encoded using * UTF-8. <strong>Note:</strong> This method may only be called if {@link #getDataFile()} is {@code null} as * otherwise the downloaded data has been written directly to disk. * * @return The possibly empty data string, never {@code null}. */
public String getDataString() { if ( dataFile != null || dataBytes == null ) { return ""; } return new String( dataBytes.toByteArray(), StandardCharsets.UTF_8 ); }
Sets the listener that is to be notified during the transfer.
Params:
  • listener – The listener to notify of progress, may be null.
Returns:This task for chaining, never null.
/** * Sets the listener that is to be notified during the transfer. * * @param listener The listener to notify of progress, may be {@code null}. * @return This task for chaining, never {@code null}. */
public GetTask setListener( TransportListener listener ) { super.setListener( listener ); return this; }
Gets the checksums which the remote repository advertises for the resource. The map is keyed by algorithm name (cf. MessageDigest.getInstance(String)) and the values are hexadecimal representations of the corresponding value. Note: This is optional data that a transporter may return if the underlying transport protocol provides metadata (e.g. HTTP headers) along with the actual resource data.
Returns:The (read-only) checksums advertised for the downloaded resource, possibly empty but never null.
/** * Gets the checksums which the remote repository advertises for the resource. The map is keyed by algorithm name * (cf. {@link java.security.MessageDigest#getInstance(String)}) and the values are hexadecimal representations of * the corresponding value. <em>Note:</em> This is optional data that a transporter may return if the underlying * transport protocol provides metadata (e.g. HTTP headers) along with the actual resource data. * * @return The (read-only) checksums advertised for the downloaded resource, possibly empty but never {@code null}. */
public Map<String, String> getChecksums() { return checksums; }
Sets a checksum which the remote repository advertises for the resource. Note: Transporters should only use this method to record checksum information which is readily available while performing the actual download, they should not perform additional transfers to gather this data.
Params:
  • algorithm – The name of the checksum algorithm (e.g. "SHA-1", cf. MessageDigest.getInstance(String) ), may be null.
  • value – The hexadecimal representation of the checksum, may be null.
Returns:This task for chaining, never null.
/** * Sets a checksum which the remote repository advertises for the resource. <em>Note:</em> Transporters should only * use this method to record checksum information which is readily available while performing the actual download, * they should not perform additional transfers to gather this data. * * @param algorithm The name of the checksum algorithm (e.g. {@code "SHA-1"}, cf. * {@link java.security.MessageDigest#getInstance(String)} ), may be {@code null}. * @param value The hexadecimal representation of the checksum, may be {@code null}. * @return This task for chaining, never {@code null}. */
public GetTask setChecksum( String algorithm, String value ) { if ( algorithm != null ) { if ( checksums.isEmpty() ) { checksums = new HashMap<>(); } if ( value != null && value.length() > 0 ) { checksums.put( algorithm, value ); } else { checksums.remove( algorithm ); } } return this; } @Override public String toString() { return "<< " + getLocation(); } }