001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.transfer; 020 021import java.io.File; 022import java.nio.file.Path; 023 024import org.eclipse.aether.RequestTrace; 025 026/** 027 * Describes a resource being uploaded or downloaded by the repository system. 028 */ 029public final class TransferResource { 030 031 private final String repositoryId; 032 033 private final String repositoryUrl; 034 035 private final String resourceName; 036 037 private final Object resource; 038 039 private final Path path; 040 041 private final long startTime; 042 043 private final RequestTrace trace; 044 045 private long contentLength = -1L; 046 047 private long resumeOffset; 048 049 /** 050 * Creates a new transfer resource with the specified properties. 051 * 052 * @param repositoryId The ID of the repository used to transfer the resource, may be {@code null} or 053 * empty if unknown. 054 * @param repositoryUrl The base URL of the repository, may be {@code null} or empty if unknown. If not empty, a 055 * trailing slash will automatically be added if missing. 056 * @param resourceName The relative path to the resource within the repository, may be {@code null}. A leading slash 057 * (if any) will be automatically removed. 058 * @param file The source/target file involved in the transfer, may be {@code null}. 059 * @param trace The trace information, may be {@code null}. 060 * 061 * @since 1.1.0 062 * @deprecated Use {@link TransferResource(String, String, String, Path, Object, RequestTrace)} instead. 063 */ 064 @Deprecated 065 public TransferResource( 066 String repositoryId, String repositoryUrl, String resourceName, File file, RequestTrace trace) { 067 this(repositoryId, repositoryUrl, resourceName, file != null ? file.toPath() : null, null, trace); 068 } 069 070 /** 071 * Creates a new transfer resource with the specified properties. 072 * 073 * @param repositoryId The ID of the repository used to transfer the resource, may be {@code null} or 074 * empty if unknown. 075 * @param repositoryUrl The base URL of the repository, may be {@code null} or empty if unknown. If not empty, a 076 * trailing slash will automatically be added if missing. 077 * @param resourceName The relative path to the resource within the repository, may be {@code null}. A leading slash 078 * (if any) will be automatically removed. 079 * @param path The source/target file involved in the transfer, may be {@code null}. 080 * @param resource The representation of this resource, may be {@code null}. 081 * @param trace The trace information, may be {@code null}. 082 * 083 * @since 2.0.0 084 */ 085 public TransferResource( 086 String repositoryId, 087 String repositoryUrl, 088 String resourceName, 089 Path path, 090 Object resource, 091 RequestTrace trace) { 092 if (repositoryId == null || repositoryId.isEmpty()) { 093 this.repositoryId = ""; 094 } else { 095 this.repositoryId = repositoryId; 096 } 097 098 if (repositoryUrl == null || repositoryUrl.isEmpty()) { 099 this.repositoryUrl = ""; 100 } else if (repositoryUrl.endsWith("/")) { 101 this.repositoryUrl = repositoryUrl; 102 } else { 103 this.repositoryUrl = repositoryUrl + '/'; 104 } 105 106 if (resourceName == null || resourceName.isEmpty()) { 107 this.resourceName = ""; 108 } else if (resourceName.startsWith("/")) { 109 this.resourceName = resourceName.substring(1); 110 } else { 111 this.resourceName = resourceName; 112 } 113 114 this.path = path; 115 this.resource = resource; 116 this.trace = trace; 117 this.startTime = System.currentTimeMillis(); 118 } 119 120 /** 121 * The ID of the repository, e.g., "central". 122 * 123 * @return The ID of the repository or an empty string if unknown, never {@code null}. 124 * 125 * @since 1.1.0 126 */ 127 public String getRepositoryId() { 128 return repositoryId; 129 } 130 131 /** 132 * The base URL of the repository, e.g. "https://repo1.maven.org/maven2/". Unless the URL is unknown, it will be 133 * terminated by a trailing slash. 134 * 135 * @return The base URL of the repository or an empty string if unknown, never {@code null}. 136 */ 137 public String getRepositoryUrl() { 138 return repositoryUrl; 139 } 140 141 /** 142 * The path of the resource relative to the repository's base URL, e.g. "org/apache/maven/maven/3.0/maven-3.0.pom". 143 * 144 * @return The path of the resource, never {@code null}. 145 */ 146 public String getResourceName() { 147 return resourceName; 148 } 149 150 /** 151 * The representation of "resource", if any. The content of this field may be 152 * {@link org.eclipse.aether.artifact.Artifact} or {@link org.eclipse.aether.metadata.Metadata} or {@code null} 153 * in case of some legacy flow. Preferred way to handle returned value is with {@code instanceof}. 154 * 155 * @return The representation of this resource, may be {@code null}. 156 * @since 2.0.0 157 */ 158 public Object getResource() { 159 return resource; 160 } 161 162 /** 163 * Gets the local file being uploaded or downloaded. When the repository system merely checks for the existence of a 164 * remote resource, no local file will be involved in the transfer. 165 * 166 * @return The source/target file involved in the transfer or {@code null} if none. 167 * @deprecated Use {@link #getPath()} instead. 168 */ 169 @Deprecated 170 public File getFile() { 171 return path != null ? path.toFile() : null; 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 * @since 2.0.0 180 */ 181 public Path getPath() { 182 return path; 183 } 184 185 /** 186 * The size of the resource in bytes. Note that the size of a resource during downloads might be unknown to the 187 * client which is usually the case when transfers employ compression like gzip. In general, the content length is 188 * not known until the transfer has {@link TransferListener#transferStarted(TransferEvent) started}. 189 * 190 * @return The size of the resource in bytes or a negative value if unknown. 191 */ 192 public long getContentLength() { 193 return contentLength; 194 } 195 196 /** 197 * Sets the size of the resource in bytes. 198 * 199 * @param contentLength The size of the resource in bytes or a negative value if unknown. 200 * @return This resource for chaining, never {@code null}. 201 */ 202 public TransferResource setContentLength(long contentLength) { 203 this.contentLength = contentLength; 204 return this; 205 } 206 207 /** 208 * Gets the byte offset within the resource from which the download starts. A positive offset indicates a previous 209 * download attempt is being resumed, {@code 0} means the transfer starts at the first byte. 210 * 211 * @return The zero-based index of the first byte being transferred, never negative. 212 */ 213 public long getResumeOffset() { 214 return resumeOffset; 215 } 216 217 /** 218 * Sets the byte offset within the resource at which the download starts. 219 * 220 * @param resumeOffset The zero-based index of the first byte being transferred, must not be negative. 221 * @return This resource for chaining, never {@code null}. 222 */ 223 public TransferResource setResumeOffset(long resumeOffset) { 224 if (resumeOffset < 0L) { 225 throw new IllegalArgumentException("resume offset cannot be negative"); 226 } 227 this.resumeOffset = resumeOffset; 228 return this; 229 } 230 231 /** 232 * Gets the timestamp when the transfer of this resource was started. 233 * 234 * @return The timestamp when the transfer of this resource was started. 235 */ 236 public long getTransferStartTime() { 237 return startTime; 238 } 239 240 /** 241 * Gets the trace information that describes the higher level request/operation during which this resource is 242 * transferred. 243 * 244 * @return The trace information about the higher level operation or {@code null} if none. 245 */ 246 public RequestTrace getTrace() { 247 return trace; 248 } 249 250 @Override 251 public String toString() { 252 return getRepositoryUrl() + getResourceName() + " <> " + getPath(); 253 } 254}