View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.transfer;
20  
21  import java.io.File;
22  import java.nio.file.Path;
23  import java.time.Clock;
24  import java.time.Instant;
25  
26  import org.eclipse.aether.RequestTrace;
27  
28  /**
29   * Describes a resource being uploaded or downloaded by the repository system.
30   */
31  public final class TransferResource {
32  
33      private static Clock clock = Clock.systemUTC();
34  
35      private final String repositoryId;
36  
37      private final String repositoryUrl;
38  
39      private final String resourceName;
40  
41      private final Object resource;
42  
43      private final Path path;
44  
45      private final Instant startTime;
46  
47      private final RequestTrace trace;
48  
49      private long contentLength = -1L;
50  
51      private long resumeOffset;
52  
53      public static Clock getClock() {
54          return clock;
55      }
56  
57      public static void setClock(Clock clock) {
58          TransferResource.clock = clock;
59      }
60  
61      /**
62       * Creates a new transfer resource with the specified properties.
63       *
64       * @param repositoryId The ID of the repository used to transfer the resource, may be {@code null} or
65       *                     empty if unknown.
66       * @param repositoryUrl The base URL of the repository, may be {@code null} or empty if unknown. If not empty, a
67       *            trailing slash will automatically be added if missing.
68       * @param resourceName The relative path to the resource within the repository, may be {@code null}. A leading slash
69       *            (if any) will be automatically removed.
70       * @param file The source/target file involved in the transfer, may be {@code null}.
71       * @param trace The trace information, may be {@code null}.
72       *
73       * @since 1.1.0
74       * @deprecated Use {@link TransferResource(String, String, String, Path, Object, RequestTrace)} instead.
75       */
76      @Deprecated
77      public TransferResource(
78              String repositoryId, String repositoryUrl, String resourceName, File file, RequestTrace trace) {
79          this(repositoryId, repositoryUrl, resourceName, file != null ? file.toPath() : null, null, trace);
80      }
81  
82      /**
83       * Creates a new transfer resource with the specified properties.
84       *
85       * @param repositoryId The ID of the repository used to transfer the resource, may be {@code null} or
86       *                     empty if unknown.
87       * @param repositoryUrl The base URL of the repository, may be {@code null} or empty if unknown. If not empty, a
88       *            trailing slash will automatically be added if missing.
89       * @param resourceName The relative path to the resource within the repository, may be {@code null}. A leading slash
90       *            (if any) will be automatically removed.
91       * @param path The source/target file involved in the transfer, may be {@code null}.
92       * @param resource The representation of this resource, may be {@code null}.
93       * @param trace The trace information, may be {@code null}.
94       *
95       * @since 2.0.0
96       */
97      public TransferResource(
98              String repositoryId,
99              String repositoryUrl,
100             String resourceName,
101             Path path,
102             Object resource,
103             RequestTrace trace) {
104         if (repositoryId == null || repositoryId.isEmpty()) {
105             this.repositoryId = "";
106         } else {
107             this.repositoryId = repositoryId;
108         }
109 
110         if (repositoryUrl == null || repositoryUrl.isEmpty()) {
111             this.repositoryUrl = "";
112         } else if (repositoryUrl.endsWith("/")) {
113             this.repositoryUrl = repositoryUrl;
114         } else {
115             this.repositoryUrl = repositoryUrl + '/';
116         }
117 
118         if (resourceName == null || resourceName.isEmpty()) {
119             this.resourceName = "";
120         } else if (resourceName.startsWith("/")) {
121             this.resourceName = resourceName.substring(1);
122         } else {
123             this.resourceName = resourceName;
124         }
125 
126         this.path = path;
127         this.resource = resource;
128         this.trace = trace;
129         this.startTime = getClock().instant();
130     }
131 
132     /**
133      * The ID of the repository, e.g., "central".
134      *
135      * @return The ID of the repository or an empty string if unknown, never {@code null}.
136      *
137      * @since 1.1.0
138      */
139     public String getRepositoryId() {
140         return repositoryId;
141     }
142 
143     /**
144      * The base URL of the repository, e.g. "https://repo1.maven.org/maven2/". Unless the URL is unknown, it will be
145      * terminated by a trailing slash.
146      *
147      * @return The base URL of the repository or an empty string if unknown, never {@code null}.
148      */
149     public String getRepositoryUrl() {
150         return repositoryUrl;
151     }
152 
153     /**
154      * The path of the resource relative to the repository's base URL, e.g. "org/apache/maven/maven/3.0/maven-3.0.pom".
155      *
156      * @return The path of the resource, never {@code null}.
157      */
158     public String getResourceName() {
159         return resourceName;
160     }
161 
162     /**
163      * The representation of "resource", if any. The content of this field may be
164      * {@link org.eclipse.aether.artifact.Artifact} or {@link org.eclipse.aether.metadata.Metadata} or {@code null}
165      * in case of some legacy flow. Preferred way to handle returned value is with {@code instanceof}.
166      *
167      * @return The representation of this resource, may be {@code null}.
168      * @since 2.0.0
169      */
170     public Object getResource() {
171         return resource;
172     }
173 
174     /**
175      * Gets the local file being uploaded or downloaded. When the repository system merely checks for the existence of a
176      * remote resource, no local file will be involved in the transfer.
177      *
178      * @return The source/target file involved in the transfer or {@code null} if none.
179      * @deprecated Use {@link #getPath()} instead.
180      */
181     @Deprecated
182     public File getFile() {
183         return path != null ? path.toFile() : null;
184     }
185 
186     /**
187      * Gets the local file being uploaded or downloaded. When the repository system merely checks for the existence of a
188      * remote resource, no local file will be involved in the transfer.
189      *
190      * @return The source/target file involved in the transfer or {@code null} if none.
191      * @since 2.0.0
192      */
193     public Path getPath() {
194         return path;
195     }
196 
197     /**
198      * The size of the resource in bytes. Note that the size of a resource during downloads might be unknown to the
199      * client which is usually the case when transfers employ compression like gzip. In general, the content length is
200      * not known until the transfer has {@link TransferListener#transferStarted(TransferEvent) started}.
201      *
202      * @return The size of the resource in bytes or a negative value if unknown.
203      */
204     public long getContentLength() {
205         return contentLength;
206     }
207 
208     /**
209      * Sets the size of the resource in bytes.
210      *
211      * @param contentLength The size of the resource in bytes or a negative value if unknown.
212      * @return This resource for chaining, never {@code null}.
213      */
214     public TransferResource setContentLength(long contentLength) {
215         this.contentLength = contentLength;
216         return this;
217     }
218 
219     /**
220      * Gets the byte offset within the resource from which the download starts. A positive offset indicates a previous
221      * download attempt is being resumed, {@code 0} means the transfer starts at the first byte.
222      *
223      * @return The zero-based index of the first byte being transferred, never negative.
224      */
225     public long getResumeOffset() {
226         return resumeOffset;
227     }
228 
229     /**
230      * Sets the byte offset within the resource at which the download starts.
231      *
232      * @param resumeOffset The zero-based index of the first byte being transferred, must not be negative.
233      * @return This resource for chaining, never {@code null}.
234      */
235     public TransferResource setResumeOffset(long resumeOffset) {
236         if (resumeOffset < 0L) {
237             throw new IllegalArgumentException("resume offset cannot be negative");
238         }
239         this.resumeOffset = resumeOffset;
240         return this;
241     }
242 
243     /**
244      * Gets the timestamp when the transfer of this resource was started.
245      *
246      * @return The timestamp when the transfer of this resource was started.
247      * @deprecated use {@link #getStartTime()}
248      */
249     @Deprecated
250     public long getTransferStartTime() {
251         return startTime.toEpochMilli();
252     }
253 
254     /**
255      * Gets the timestamp when the transfer of this resource was started.
256      *
257      * @return The timestamp when the transfer of this resource was started.
258      */
259     public Instant getStartTime() {
260         return startTime;
261     }
262 
263     /**
264      * Gets the trace information that describes the higher level request/operation during which this resource is
265      * transferred.
266      *
267      * @return The trace information about the higher level operation or {@code null} if none.
268      */
269     public RequestTrace getTrace() {
270         return trace;
271     }
272 
273     @Override
274     public String toString() {
275         return getRepositoryUrl() + getResourceName() + " <> " + getPath();
276     }
277 }