View Javadoc
1   package org.apache.maven.artifact.repository;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.Collections;
24  import java.util.List;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.artifact.metadata.ArtifactMetadata;
28  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
29  import org.apache.maven.repository.Proxy;
30  
31  /**
32   * Abstraction of an artifact repository. Artifact repositories can be remote, local, or even build reactor or
33   * IDE workspace.
34   */
35  //TODO completely separate local and remote artifact repositories
36  public class MavenArtifactRepository
37      implements ArtifactRepository
38  {
39      private String id;
40  
41      private String url;
42  
43      private String basedir;
44  
45      private String protocol;
46  
47      private ArtifactRepositoryLayout layout;
48  
49      private ArtifactRepositoryPolicy snapshots;
50  
51      private ArtifactRepositoryPolicy releases;
52  
53      private Authentication authentication;
54  
55      private Proxy proxy;
56  
57      private List<ArtifactRepository> mirroredRepositories = Collections.emptyList();
58  
59      public MavenArtifactRepository()
60      {
61      }
62  
63      /**
64       * Create a remote download repository.
65       *
66       * @param id        the unique identifier of the repository
67       * @param url       the URL of the repository
68       * @param layout    the layout of the repository
69       * @param snapshots the policies to use for snapshots
70       * @param releases  the policies to use for releases
71       */
72      public MavenArtifactRepository( String id, String url, ArtifactRepositoryLayout layout,
73                                      ArtifactRepositoryPolicy snapshots, ArtifactRepositoryPolicy releases )
74      {
75          this.id = id;
76          this.url = url;
77          this.layout = layout;
78          this.snapshots = snapshots;
79          this.releases = releases;
80          //
81          // Derive these from the URL
82          //
83          this.protocol = protocol( url );
84          this.basedir = basedir( url );
85      }
86  
87      public String pathOf( Artifact artifact )
88      {
89          return layout.pathOf( artifact );
90      }
91  
92      public String pathOfRemoteRepositoryMetadata( ArtifactMetadata artifactMetadata )
93      {
94          return layout.pathOfRemoteRepositoryMetadata( artifactMetadata );
95      }
96  
97      public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository )
98      {
99          return layout.pathOfLocalRepositoryMetadata( metadata, repository );
100     }
101 
102     public void setLayout( ArtifactRepositoryLayout layout )
103     {
104         this.layout = layout;
105     }
106 
107     public ArtifactRepositoryLayout getLayout()
108     {
109         return layout;
110     }
111 
112     public void setSnapshotUpdatePolicy( ArtifactRepositoryPolicy snapshots )
113     {
114         this.snapshots = snapshots;
115     }
116 
117     public ArtifactRepositoryPolicy getSnapshots()
118     {
119         return snapshots;
120     }
121 
122     public void setReleaseUpdatePolicy( ArtifactRepositoryPolicy releases )
123     {
124         this.releases = releases;
125     }
126 
127     public ArtifactRepositoryPolicy getReleases()
128     {
129         return releases;
130     }
131 
132     public String getKey()
133     {
134         return getId();
135     }
136 
137     public String toString()
138     {
139         StringBuilder sb = new StringBuilder( 256 );
140 
141         sb.append( "      id: " ).append( getId() ).append( '\n' );
142         sb.append( "      url: " ).append( getUrl() ).append( '\n' );
143         sb.append( "   layout: " ).append( layout != null ? layout : "none" ).append( '\n' );
144 
145         if ( proxy != null )
146         {
147             sb.append( "    proxy: " ).append( proxy.getHost() ).append( ':' ).append( proxy.getPort() ).append( '\n' );
148         }
149 
150         if ( snapshots != null )
151         {
152             sb.append( "snapshots: [enabled => " ).append( snapshots.isEnabled() );
153             sb.append( ", update => " ).append( snapshots.getUpdatePolicy() ).append( "]\n" );
154         }
155 
156         if ( releases != null )
157         {
158             sb.append( " releases: [enabled => " ).append( releases.isEnabled() );
159             sb.append( ", update => " ).append( releases.getUpdatePolicy() ).append( "]\n" );
160         }
161 
162         return sb.toString();
163     }
164 
165     public Artifact find( Artifact artifact )
166     {
167         File artifactFile = new File( getBasedir(), pathOf( artifact ) );
168 
169         // We need to set the file here or the resolver will fail with an NPE, not fully equipped to deal
170         // with multiple local repository implementations yet.
171         artifact.setFile( artifactFile );
172 
173         return artifact;
174     }
175 
176     public List<String> findVersions( Artifact artifact )
177     {
178         return Collections.emptyList();
179     }
180 
181     public String getId()
182     {
183         return id;
184     }
185 
186     public String getUrl()
187     {
188         return url;
189     }
190 
191     public String getBasedir()
192     {
193         return basedir;
194     }
195 
196     public String getProtocol()
197     {
198         return protocol;
199     }
200 
201     public void setId( String id )
202     {
203         this.id = id;
204     }
205 
206     public void setUrl( String url )
207     {
208         this.url = url;
209 
210         this.protocol = protocol( url );
211         this.basedir = basedir( url );
212     }
213 
214     // Path Utils
215 
216     /**
217      * Return the protocol name.
218      * <br>
219      * E.g: for input
220      * <code>http://www.codehaus.org</code> this method will return <code>http</code>
221      *
222      * @param url the url
223      * @return the host name
224      */
225     private static String protocol( final String url )
226     {
227         final int pos = url.indexOf( ':' );
228 
229         if ( pos == -1 )
230         {
231             return "";
232         }
233         return url.substring( 0, pos ).trim();
234     }
235 
236     /**
237      * Derive the path portion of the given URL.
238      *
239      * @param url the repository URL
240      * @return the basedir of the repository
241      * TODO need to URL decode for spaces?
242      */
243     private String basedir( String url )
244     {
245         String retValue = null;
246 
247         if ( protocol.equalsIgnoreCase( "file" ) )
248         {
249             retValue = url.substring( protocol.length() + 1 );
250             retValue = decode( retValue );
251             // special case: if omitted // on protocol, keep path as is
252             if ( retValue.startsWith( "//" ) )
253             {
254                 retValue = retValue.substring( 2 );
255 
256                 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) )
257                 {
258                     // special case: if there is a windows drive letter, then keep the original return value
259                     retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
260                 }
261                 else
262                 {
263                     // Now we expect the host
264                     int index = retValue.indexOf( '/' );
265                     if ( index >= 0 )
266                     {
267                         retValue = retValue.substring( index + 1 );
268                     }
269 
270                     // special case: if there is a windows drive letter, then keep the original return value
271                     if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) )
272                     {
273                         retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
274                     }
275                     else if ( index >= 0 )
276                     {
277                         // leading / was previously stripped
278                         retValue = "/" + retValue;
279                     }
280                 }
281             }
282 
283             // special case: if there is a windows drive letter using |, switch to :
284             if ( retValue.length() >= 2 && retValue.charAt( 1 ) == '|' )
285             {
286                 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
287             }
288 
289             // normalize separators
290             retValue = new File( retValue ).getPath();
291         }
292 
293         if ( retValue == null )
294         {
295             retValue = "/";
296         }
297         return retValue.trim();
298     }
299 
300     /**
301      * Decodes the specified (portion of a) URL. <strong>Note:</strong> This decoder assumes that ISO-8859-1 is used to
302      * convert URL-encoded bytes to characters.
303      *
304      * @param url The URL to decode, may be <code>null</code>.
305      * @return The decoded URL or <code>null</code> if the input was <code>null</code>.
306      */
307     private static String decode( String url )
308     {
309         String decoded = url;
310         if ( url != null )
311         {
312             int pos = -1;
313             while ( ( pos = decoded.indexOf( '%', pos + 1 ) ) >= 0 )
314             {
315                 if ( pos + 2 < decoded.length() )
316                 {
317                     String hexStr = decoded.substring( pos + 1, pos + 3 );
318                     char ch = (char) Integer.parseInt( hexStr, 16 );
319                     decoded = decoded.substring( 0, pos ) + ch + decoded.substring( pos + 3 );
320                 }
321             }
322         }
323         return decoded;
324     }
325 
326     public int hashCode()
327     {
328         final int prime = 31;
329         int result = 1;
330         result = prime * result + ( ( getId() == null ) ? 0 : getId().hashCode() );
331         return result;
332     }
333 
334     public boolean equals( Object obj )
335     {
336         if ( this == obj )
337         {
338             return true;
339         }
340         if ( obj == null )
341         {
342             return false;
343         }
344         if ( getClass() != obj.getClass() )
345         {
346             return false;
347         }
348 
349         ArtifactRepository other = (ArtifactRepository) obj;
350 
351         return eq( getId(), other.getId() );
352     }
353 
354     protected static <T> boolean eq( T s1, T s2 )
355     {
356         return s1 != null ? s1.equals( s2 ) : s2 == null;
357     }
358 
359     public Authentication getAuthentication()
360     {
361         return authentication;
362     }
363 
364     public void setAuthentication( Authentication authentication )
365     {
366         this.authentication = authentication;
367     }
368 
369     public Proxy getProxy()
370     {
371         return proxy;
372     }
373 
374     public void setProxy( Proxy proxy )
375     {
376         this.proxy = proxy;
377     }
378 
379     public boolean isBlacklisted()
380     {
381         return false;
382     }
383 
384     public void setBlacklisted( boolean blackListed )
385     {
386         // no op
387     }
388 
389     public boolean isUniqueVersion()
390     {
391         return true;
392     }
393 
394     public boolean isProjectAware()
395     {
396         return false;
397     }
398 
399     public List<ArtifactRepository> getMirroredRepositories()
400     {
401         return mirroredRepositories;
402     }
403 
404     public void setMirroredRepositories( List<ArtifactRepository> mirroredRepositories )
405     {
406         if ( mirroredRepositories != null )
407         {
408             this.mirroredRepositories = Collections.unmodifiableList( mirroredRepositories );
409         }
410         else
411         {
412             this.mirroredRepositories = Collections.emptyList();
413         }
414     }
415 
416 }