001 package org.apache.maven.artifact.repository; 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 022 import java.io.File; 023 import java.util.Collections; 024 import java.util.List; 025 026 import org.apache.maven.artifact.Artifact; 027 import org.apache.maven.artifact.metadata.ArtifactMetadata; 028 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; 029 import org.apache.maven.repository.Proxy; 030 031 //TODO: completely separate local and remote artifact repositories 032 public class MavenArtifactRepository 033 implements ArtifactRepository 034 { 035 private String id; 036 037 private String url; 038 039 private String basedir; 040 041 private String protocol; 042 043 private ArtifactRepositoryLayout layout; 044 045 private ArtifactRepositoryPolicy snapshots; 046 047 private ArtifactRepositoryPolicy releases; 048 049 private Authentication authentication; 050 051 private Proxy proxy; 052 053 private List<ArtifactRepository> mirroredRepositories = Collections.emptyList(); 054 055 public MavenArtifactRepository() 056 { 057 } 058 059 /** 060 * Create a remote download repository. 061 * 062 * @param id the unique identifier of the repository 063 * @param url the URL of the repository 064 * @param layout the layout of the repository 065 * @param snapshots the policies to use for snapshots 066 * @param releases the policies to use for releases 067 */ 068 public MavenArtifactRepository( String id, String url, ArtifactRepositoryLayout layout, 069 ArtifactRepositoryPolicy snapshots, ArtifactRepositoryPolicy releases ) 070 { 071 this.id = id; 072 this.url = url; 073 this.layout = layout; 074 this.snapshots = snapshots; 075 this.releases = releases; 076 // 077 // Derive these from the URL 078 // 079 this.protocol = protocol( url ); 080 this.basedir = basedir( url ); 081 } 082 083 public String pathOf( Artifact artifact ) 084 { 085 return layout.pathOf( artifact ); 086 } 087 088 public String pathOfRemoteRepositoryMetadata( ArtifactMetadata artifactMetadata ) 089 { 090 return layout.pathOfRemoteRepositoryMetadata( artifactMetadata ); 091 } 092 093 public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository ) 094 { 095 return layout.pathOfLocalRepositoryMetadata( metadata, repository ); 096 } 097 098 public void setLayout( ArtifactRepositoryLayout layout ) 099 { 100 this.layout = layout; 101 } 102 103 public ArtifactRepositoryLayout getLayout() 104 { 105 return layout; 106 } 107 108 public void setSnapshotUpdatePolicy( ArtifactRepositoryPolicy snapshots ) 109 { 110 this.snapshots = snapshots; 111 } 112 113 public ArtifactRepositoryPolicy getSnapshots() 114 { 115 return snapshots; 116 } 117 118 public void setReleaseUpdatePolicy( ArtifactRepositoryPolicy releases ) 119 { 120 this.releases = releases; 121 } 122 123 public ArtifactRepositoryPolicy getReleases() 124 { 125 return releases; 126 } 127 128 public String getKey() 129 { 130 return getId(); 131 } 132 133 public String toString() 134 { 135 StringBuilder sb = new StringBuilder(); 136 137 sb.append( " id: " ).append( getId() ).append( "\n" ); 138 sb.append( " url: " ).append( getUrl() ).append( "\n" ); 139 sb.append( " layout: " ).append( layout != null ? layout : "none" ).append( "\n" ); 140 141 if ( snapshots != null ) 142 { 143 sb.append( "snapshots: [enabled => " ).append( snapshots.isEnabled() ); 144 sb.append( ", update => " ).append( snapshots.getUpdatePolicy() ).append( "]\n" ); 145 } 146 147 if ( releases != null ) 148 { 149 sb.append( " releases: [enabled => " ).append( releases.isEnabled() ); 150 sb.append( ", update => " ).append( releases.getUpdatePolicy() ).append( "]\n" ); 151 } 152 153 return sb.toString(); 154 } 155 156 public Artifact find( Artifact artifact ) 157 { 158 File artifactFile = new File( getBasedir(), pathOf( artifact ) ); 159 160 // We need to set the file here or the resolver will fail with an NPE, not fully equipped to deal 161 // with multiple local repository implementations yet. 162 artifact.setFile( artifactFile ); 163 164 return artifact; 165 } 166 167 public List<String> findVersions( Artifact artifact ) 168 { 169 return Collections.emptyList(); 170 } 171 172 public String getId() 173 { 174 return id; 175 } 176 177 public String getUrl() 178 { 179 return url; 180 } 181 182 public String getBasedir() 183 { 184 return basedir; 185 } 186 187 public String getProtocol() 188 { 189 return protocol; 190 } 191 192 public void setId( String id ) 193 { 194 this.id = id; 195 } 196 197 public void setUrl( String url ) 198 { 199 this.url = url; 200 201 this.protocol = protocol( url ); 202 this.basedir = basedir( url ); 203 } 204 205 // Path Utils 206 207 /** 208 * /** 209 * Return the protocol name. 210 * <br/> 211 * E.g: for input 212 * <code>http://www.codehause.org</code> this method will return <code>http</code> 213 * 214 * @param url the url 215 * @return the host name 216 */ 217 private static String protocol( final String url ) 218 { 219 final int pos = url.indexOf( ":" ); 220 221 if ( pos == -1 ) 222 { 223 return ""; 224 } 225 return url.substring( 0, pos ).trim(); 226 } 227 228 /** 229 * Derive the path portion of the given URL. 230 * 231 * @param url the repository URL 232 * @return the basedir of the repository 233 * @todo need to URL decode for spaces? 234 */ 235 private String basedir( String url ) 236 { 237 String retValue = null; 238 239 if ( protocol.equalsIgnoreCase( "file" ) ) 240 { 241 retValue = url.substring( protocol.length() + 1 ); 242 retValue = decode( retValue ); 243 // special case: if omitted // on protocol, keep path as is 244 if ( retValue.startsWith( "//" ) ) 245 { 246 retValue = retValue.substring( 2 ); 247 248 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) ) 249 { 250 // special case: if there is a windows drive letter, then keep the original return value 251 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 252 } 253 else 254 { 255 // Now we expect the host 256 int index = retValue.indexOf( "/" ); 257 if ( index >= 0 ) 258 { 259 retValue = retValue.substring( index + 1 ); 260 } 261 262 // special case: if there is a windows drive letter, then keep the original return value 263 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) ) 264 { 265 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 266 } 267 else if ( index >= 0 ) 268 { 269 // leading / was previously stripped 270 retValue = "/" + retValue; 271 } 272 } 273 } 274 275 // special case: if there is a windows drive letter using |, switch to : 276 if ( retValue.length() >= 2 && retValue.charAt( 1 ) == '|' ) 277 { 278 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 279 } 280 281 // normalize separators 282 retValue = new File( retValue ).getPath(); 283 } 284 285 if ( retValue == null ) 286 { 287 retValue = "/"; 288 } 289 return retValue.trim(); 290 } 291 292 /** 293 * Decodes the specified (portion of a) URL. <strong>Note:</strong> This decoder assumes that ISO-8859-1 is used to 294 * convert URL-encoded octets to characters. 295 * 296 * @param url The URL to decode, may be <code>null</code>. 297 * @return The decoded URL or <code>null</code> if the input was <code>null</code>. 298 */ 299 private static String decode( String url ) 300 { 301 String decoded = url; 302 if ( url != null ) 303 { 304 int pos = -1; 305 while ( ( pos = decoded.indexOf( '%', pos + 1 ) ) >= 0 ) 306 { 307 if ( pos + 2 < decoded.length() ) 308 { 309 String hexStr = decoded.substring( pos + 1, pos + 3 ); 310 char ch = (char) Integer.parseInt( hexStr, 16 ); 311 decoded = decoded.substring( 0, pos ) + ch + decoded.substring( pos + 3 ); 312 } 313 } 314 } 315 return decoded; 316 } 317 318 public int hashCode() 319 { 320 final int prime = 31; 321 int result = 1; 322 result = prime * result + ( ( getId() == null ) ? 0 : getId().hashCode() ); 323 return result; 324 } 325 326 public boolean equals( Object obj ) 327 { 328 if ( this == obj ) 329 { 330 return true; 331 } 332 if ( obj == null ) 333 { 334 return false; 335 } 336 if ( getClass() != obj.getClass() ) 337 { 338 return false; 339 } 340 341 ArtifactRepository other = (ArtifactRepository) obj; 342 343 return eq( getId(), other.getId() ); 344 } 345 346 protected static <T> boolean eq( T s1, T s2 ) 347 { 348 return s1 != null ? s1.equals( s2 ) : s2 == null; 349 } 350 351 public Authentication getAuthentication() 352 { 353 return authentication; 354 } 355 356 public void setAuthentication( Authentication authentication ) 357 { 358 this.authentication = authentication; 359 } 360 361 public Proxy getProxy() 362 { 363 return proxy; 364 } 365 366 public void setProxy( Proxy proxy ) 367 { 368 this.proxy = proxy; 369 } 370 371 public boolean isBlacklisted() 372 { 373 return false; 374 } 375 376 public void setBlacklisted( boolean blackListed ) 377 { 378 // no op 379 } 380 381 public boolean isUniqueVersion() 382 { 383 return true; 384 } 385 386 public boolean isProjectAware() 387 { 388 return false; 389 } 390 391 public List<ArtifactRepository> getMirroredRepositories() 392 { 393 return mirroredRepositories; 394 } 395 396 public void setMirroredRepositories( List<ArtifactRepository> mirroredRepositories ) 397 { 398 if ( mirroredRepositories != null ) 399 { 400 this.mirroredRepositories = mirroredRepositories; 401 } 402 else 403 { 404 this.mirroredRepositories = Collections.emptyList(); 405 } 406 } 407 408 }