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 }