001package org.eclipse.aether.spi.connector.transport;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  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,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.ByteArrayInputStream;
023import java.io.File;
024import java.io.FileInputStream;
025import java.io.IOException;
026import java.io.InputStream;
027import java.net.URI;
028import java.nio.charset.StandardCharsets;
029
030/**
031 * A task to upload a resource to the remote repository.
032 *
033 * @see Transporter#put(PutTask)
034 */
035public final class PutTask
036    extends TransportTask
037{
038
039    private File dataFile;
040
041    private byte[] dataBytes = EMPTY;
042
043    /**
044     * Creates a new task for the specified remote resource.
045     * 
046     * @param location The relative location of the resource in the remote repository, must not be {@code null}.
047     */
048    public PutTask( URI location )
049    {
050        setLocation( location );
051    }
052
053    /**
054     * Opens an input stream for the data to be uploaded. The length of the stream can be queried via
055     * {@link #getDataLength()}. It's the responsibility of the caller to close the provided stream.
056     * 
057     * @return The input stream for the data, never {@code null}. The stream is unbuffered.
058     * @throws IOException If the stream could not be opened.
059     */
060    public InputStream newInputStream()
061        throws IOException
062    {
063        if ( dataFile != null )
064        {
065            return new FileInputStream( dataFile );
066        }
067        return new ByteArrayInputStream( dataBytes );
068    }
069
070    /**
071     * Gets the total number of bytes to be uploaded.
072     * 
073     * @return The total number of bytes to be uploaded.
074     */
075    public long getDataLength()
076    {
077        if ( dataFile != null )
078        {
079            return dataFile.length();
080        }
081        return dataBytes.length;
082    }
083
084    /**
085     * Gets the file (if any) with the data to be uploaded.
086     * 
087     * @return The data file or {@code null} if the data resides in memory.
088     */
089    public File getDataFile()
090    {
091        return dataFile;
092    }
093
094    /**
095     * Sets the file with the data to be uploaded. To upload some data residing already in memory, use
096     * {@link #setDataString(String)} or {@link #setDataBytes(byte[])}.
097     * 
098     * @param dataFile The data file, may be {@code null} if the resource data is provided directly from memory.
099     * @return This task for chaining, never {@code null}.
100     */
101    public PutTask setDataFile( File dataFile )
102    {
103        this.dataFile = dataFile;
104        dataBytes = EMPTY;
105        return this;
106    }
107
108    /**
109     * Sets the binary data to be uploaded.
110     * 
111     * @param bytes The binary data, may be {@code null}.
112     * @return This task for chaining, never {@code null}.
113     */
114    public PutTask setDataBytes( byte[] bytes )
115    {
116        this.dataBytes = ( bytes != null ) ? bytes : EMPTY;
117        dataFile = null;
118        return this;
119    }
120
121    /**
122     * Sets the textual data to be uploaded. The text is encoded using UTF-8 before transmission.
123     *
124     * @param str The textual data, may be {@code null}.
125     * @return This task for chaining, never {@code null}.
126     */
127    public PutTask setDataString( String str )
128    {
129        return setDataBytes( ( str != null ) ? str.getBytes( StandardCharsets.UTF_8 ) : null );
130    }
131
132    /**
133     * Sets the listener that is to be notified during the transfer.
134     *
135     * @param listener The listener to notify of progress, may be {@code null}.
136     * @return This task for chaining, never {@code null}.
137     */
138    public PutTask setListener( TransportListener listener )
139    {
140        super.setListener( listener );
141        return this;
142    }
143
144    @Override
145    public String toString()
146    {
147        return ">> " + getLocation();
148    }
149
150}