001package 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 022import java.io.File; 023import java.util.Collections; 024import java.util.List; 025 026import org.apache.maven.artifact.Artifact; 027import org.apache.maven.artifact.metadata.ArtifactMetadata; 028import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; 029import org.apache.maven.repository.Proxy; 030 031//TODO: completely separate local and remote artifact repositories 032public 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 ( proxy != null ) 142 { 143 sb.append( " proxy: " ).append( proxy.getHost() ).append( ":" ).append( proxy.getPort() ).append( "\n" ); 144 } 145 146 if ( snapshots != null ) 147 { 148 sb.append( "snapshots: [enabled => " ).append( snapshots.isEnabled() ); 149 sb.append( ", update => " ).append( snapshots.getUpdatePolicy() ).append( "]\n" ); 150 } 151 152 if ( releases != null ) 153 { 154 sb.append( " releases: [enabled => " ).append( releases.isEnabled() ); 155 sb.append( ", update => " ).append( releases.getUpdatePolicy() ).append( "]\n" ); 156 } 157 158 return sb.toString(); 159 } 160 161 public Artifact find( Artifact artifact ) 162 { 163 File artifactFile = new File( getBasedir(), pathOf( artifact ) ); 164 165 // We need to set the file here or the resolver will fail with an NPE, not fully equipped to deal 166 // with multiple local repository implementations yet. 167 artifact.setFile( artifactFile ); 168 169 return artifact; 170 } 171 172 public List<String> findVersions( Artifact artifact ) 173 { 174 return Collections.emptyList(); 175 } 176 177 public String getId() 178 { 179 return id; 180 } 181 182 public String getUrl() 183 { 184 return url; 185 } 186 187 public String getBasedir() 188 { 189 return basedir; 190 } 191 192 public String getProtocol() 193 { 194 return protocol; 195 } 196 197 public void setId( String id ) 198 { 199 this.id = id; 200 } 201 202 public void setUrl( String url ) 203 { 204 this.url = url; 205 206 this.protocol = protocol( url ); 207 this.basedir = basedir( url ); 208 } 209 210 // Path Utils 211 212 /** 213 * Return the protocol name. 214 * <br/> 215 * E.g: for input 216 * <code>http://www.codehause.org</code> this method will return <code>http</code> 217 * 218 * @param url the url 219 * @return the host name 220 */ 221 private static String protocol( final String url ) 222 { 223 final int pos = url.indexOf( ":" ); 224 225 if ( pos == -1 ) 226 { 227 return ""; 228 } 229 return url.substring( 0, pos ).trim(); 230 } 231 232 /** 233 * Derive the path portion of the given URL. 234 * 235 * @param url the repository URL 236 * @return the basedir of the repository 237 * @todo need to URL decode for spaces? 238 */ 239 private String basedir( String url ) 240 { 241 String retValue = null; 242 243 if ( protocol.equalsIgnoreCase( "file" ) ) 244 { 245 retValue = url.substring( protocol.length() + 1 ); 246 retValue = decode( retValue ); 247 // special case: if omitted // on protocol, keep path as is 248 if ( retValue.startsWith( "//" ) ) 249 { 250 retValue = retValue.substring( 2 ); 251 252 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) ) 253 { 254 // special case: if there is a windows drive letter, then keep the original return value 255 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 256 } 257 else 258 { 259 // Now we expect the host 260 int index = retValue.indexOf( "/" ); 261 if ( index >= 0 ) 262 { 263 retValue = retValue.substring( index + 1 ); 264 } 265 266 // special case: if there is a windows drive letter, then keep the original return value 267 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) ) 268 { 269 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 270 } 271 else if ( index >= 0 ) 272 { 273 // leading / was previously stripped 274 retValue = "/" + retValue; 275 } 276 } 277 } 278 279 // special case: if there is a windows drive letter using |, switch to : 280 if ( retValue.length() >= 2 && retValue.charAt( 1 ) == '|' ) 281 { 282 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 ); 283 } 284 285 // normalize separators 286 retValue = new File( retValue ).getPath(); 287 } 288 289 if ( retValue == null ) 290 { 291 retValue = "/"; 292 } 293 return retValue.trim(); 294 } 295 296 /** 297 * Decodes the specified (portion of a) URL. <strong>Note:</strong> This decoder assumes that ISO-8859-1 is used to 298 * convert URL-encoded bytes to characters. 299 * 300 * @param url The URL to decode, may be <code>null</code>. 301 * @return The decoded URL or <code>null</code> if the input was <code>null</code>. 302 */ 303 private static String decode( String url ) 304 { 305 String decoded = url; 306 if ( url != null ) 307 { 308 int pos = -1; 309 while ( ( pos = decoded.indexOf( '%', pos + 1 ) ) >= 0 ) 310 { 311 if ( pos + 2 < decoded.length() ) 312 { 313 String hexStr = decoded.substring( pos + 1, pos + 3 ); 314 char ch = (char) Integer.parseInt( hexStr, 16 ); 315 decoded = decoded.substring( 0, pos ) + ch + decoded.substring( pos + 3 ); 316 } 317 } 318 } 319 return decoded; 320 } 321 322 public int hashCode() 323 { 324 final int prime = 31; 325 int result = 1; 326 result = prime * result + ( ( getId() == null ) ? 0 : getId().hashCode() ); 327 return result; 328 } 329 330 public boolean equals( Object obj ) 331 { 332 if ( this == obj ) 333 { 334 return true; 335 } 336 if ( obj == null ) 337 { 338 return false; 339 } 340 if ( getClass() != obj.getClass() ) 341 { 342 return false; 343 } 344 345 ArtifactRepository other = (ArtifactRepository) obj; 346 347 return eq( getId(), other.getId() ); 348 } 349 350 protected static <T> boolean eq( T s1, T s2 ) 351 { 352 return s1 != null ? s1.equals( s2 ) : s2 == null; 353 } 354 355 public Authentication getAuthentication() 356 { 357 return authentication; 358 } 359 360 public void setAuthentication( Authentication authentication ) 361 { 362 this.authentication = authentication; 363 } 364 365 public Proxy getProxy() 366 { 367 return proxy; 368 } 369 370 public void setProxy( Proxy proxy ) 371 { 372 this.proxy = proxy; 373 } 374 375 public boolean isBlacklisted() 376 { 377 return false; 378 } 379 380 public void setBlacklisted( boolean blackListed ) 381 { 382 // no op 383 } 384 385 public boolean isUniqueVersion() 386 { 387 return true; 388 } 389 390 public boolean isProjectAware() 391 { 392 return false; 393 } 394 395 public List<ArtifactRepository> getMirroredRepositories() 396 { 397 return mirroredRepositories; 398 } 399 400 public void setMirroredRepositories( List<ArtifactRepository> mirroredRepositories ) 401 { 402 if ( mirroredRepositories != null ) 403 { 404 this.mirroredRepositories = mirroredRepositories; 405 } 406 else 407 { 408 this.mirroredRepositories = Collections.emptyList(); 409 } 410 } 411 412}