001package org.apache.maven.artifact.resolver;
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.util.Iterator;
023import java.util.List;
024
025import org.apache.maven.artifact.Artifact;
026import org.apache.maven.artifact.repository.ArtifactRepository;
027import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
028
029/**
030 * Base class for artifact resolution exceptions.
031 *
032 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
033 */
034public class AbstractArtifactResolutionException
035    extends Exception
036{
037    private String groupId;
038
039    private String artifactId;
040
041    private String version;
042
043    private String type;
044
045    private String classifier;
046
047    private Artifact artifact; 
048
049    private List<ArtifactRepository> remoteRepositories;
050
051    private final String originalMessage;
052
053    private final String path;
054
055    static final String LS = System.getProperty( "line.separator" );
056
057    protected AbstractArtifactResolutionException( String message,
058                                                   String groupId,
059                                                   String artifactId,
060                                                   String version,
061                                                   String type,
062                                                   String classifier,
063                                                   List<ArtifactRepository> remoteRepositories,
064                                                   List<String> path )
065    {
066        this( message, groupId, artifactId, version, type, classifier, remoteRepositories, path, null );
067    }
068
069    protected AbstractArtifactResolutionException( String message,
070                                                   String groupId,
071                                                   String artifactId,
072                                                   String version,
073                                                   String type,
074                                                   String classifier,
075                                                   List<ArtifactRepository> remoteRepositories,
076                                                   List<String> path,
077                                                   Throwable t )
078    {
079        super( constructMessageBase( message, groupId, artifactId, version, type, remoteRepositories, path ), t );
080
081        this.originalMessage = message;
082        this.groupId = groupId;
083        this.artifactId = artifactId;
084        this.type = type;
085        this.classifier = classifier;
086        this.version = version;
087        this.remoteRepositories = remoteRepositories;
088        this.path = constructArtifactPath( path, "" );
089    }
090
091    protected AbstractArtifactResolutionException( String message,
092                                                   Artifact artifact )
093    {
094        this( message, artifact, null );
095    }
096
097    protected AbstractArtifactResolutionException( String message,
098                                                   Artifact artifact,
099                                                   List<ArtifactRepository> remoteRepositories )
100    {
101        this( message, artifact, remoteRepositories, null );
102    }
103
104    protected AbstractArtifactResolutionException( String message,
105                                                   Artifact artifact,
106                                                   List<ArtifactRepository> remoteRepositories,
107                                                   Throwable t )
108    {
109        this( message, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getType(),
110            artifact.getClassifier(), remoteRepositories, artifact.getDependencyTrail(), t );
111        this.artifact = artifact;
112    }
113
114    public Artifact getArtifact()
115    {
116        return artifact;
117    }
118
119    public String getGroupId()
120    {
121        return groupId;
122    }
123
124    public String getArtifactId()
125    {
126        return artifactId;
127    }
128
129    public String getVersion()
130    {
131        return version;
132    }
133
134    public String getType()
135    {
136        return type;
137    }
138
139    /** @return the classifier */
140    public String getClassifier()
141    {
142        return this.classifier;
143    }
144
145    /** @return the path */
146    public String getPath()
147    {
148        return this.path;
149    }
150
151    public List<ArtifactRepository> getRemoteRepositories()
152    {
153        return remoteRepositories;
154    }
155
156    public String getOriginalMessage()
157    {
158        return originalMessage;
159    }
160
161    protected static String constructArtifactPath( List<String> path,
162                                                   String indentation )
163    {
164        StringBuilder sb = new StringBuilder();
165
166        if ( path != null )
167        {
168            sb.append( LS );
169            sb.append( indentation );
170            sb.append( "Path to dependency: " );
171            sb.append( LS );
172            int num = 1;
173            for ( Iterator<String> i = path.iterator(); i.hasNext(); num++ )
174            {
175                sb.append( indentation );
176                sb.append( "\t" );
177                sb.append( num );
178                sb.append( ") " );
179                sb.append( i.next() );
180                sb.append( LS );
181            }
182        }
183
184        return sb.toString();
185    }
186
187    private static String constructMessageBase( String message,
188                                                String groupId,
189                                                String artifactId,
190                                                String version,
191                                                String type,
192                                                List<ArtifactRepository> remoteRepositories,
193                                                List<String> path )
194    {
195        StringBuilder sb = new StringBuilder();
196
197        sb.append( message );
198
199        if ( message == null || !message.contains( "from the specified remote repositories:" ) )
200        {
201            sb.append( LS );
202            sb.append( "  " ).append( groupId ).append( ":" ).append( artifactId ).append( ":" ).append( type ).append(
203                ":" ).append( version );
204            sb.append( LS );
205            if ( remoteRepositories != null )
206            {
207                sb.append( LS );
208                sb.append( "from the specified remote repositories:" );
209                sb.append( LS ).append( "  " );
210
211                if ( remoteRepositories.isEmpty() )
212                {
213                    sb.append( "(none)" );
214                }
215
216                for ( Iterator<ArtifactRepository> i = remoteRepositories.iterator(); i.hasNext(); )
217                {
218                    ArtifactRepository remoteRepository = i.next();
219
220                    sb.append( remoteRepository.getId() );
221                    sb.append( " (" );
222                    sb.append( remoteRepository.getUrl() );
223
224                    ArtifactRepositoryPolicy releases = remoteRepository.getReleases();
225                    if ( releases != null )
226                    {
227                        sb.append( ", releases=" ).append( releases.isEnabled() );
228                    }
229
230                    ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots();
231                    if ( snapshots != null )
232                    {
233                        sb.append( ", snapshots=" ).append( snapshots.isEnabled() );
234                    }
235
236                    sb.append( ")" );
237                    if ( i.hasNext() )
238                    {
239                        sb.append( "," ).append( LS ).append( "  " );
240                    }
241                }
242            }
243
244            sb.append( constructArtifactPath( path, "" ) );
245            sb.append( LS );
246        }
247
248        return sb.toString();
249    }
250
251    protected static String constructMissingArtifactMessage( String message,
252                                                             String indentation,
253                                                             String groupId,
254                                                             String artifactId,
255                                                             String version,
256                                                             String type,
257                                                             String classifier,
258                                                             String downloadUrl,
259                                                             List<String> path )
260    {
261        StringBuilder sb = new StringBuilder( message );
262
263        if ( !"pom".equals( type ) )
264        {
265            if ( downloadUrl != null )
266            {
267                sb.append( LS );
268                sb.append( LS );
269                sb.append( indentation );
270                sb.append( "Try downloading the file manually from: " );
271                sb.append( LS );
272                sb.append( indentation );
273                sb.append( "    " );
274                sb.append( downloadUrl );
275            }
276            else
277            {
278                sb.append( LS );
279                sb.append( LS );
280                sb.append( indentation );
281                sb.append( "Try downloading the file manually from the project website." );
282            }
283
284            sb.append( LS );
285            sb.append( LS );
286            sb.append( indentation );
287            sb.append( "Then, install it using the command: " );
288            sb.append( LS );
289            sb.append( indentation );
290            sb.append( "    mvn install:install-file -DgroupId=" );
291            sb.append( groupId );
292            sb.append( " -DartifactId=" );
293            sb.append( artifactId );
294            sb.append( " -Dversion=" );
295            sb.append( version );
296
297            //insert classifier only if it was used in the artifact
298            if ( classifier != null && !classifier.equals( "" ) )
299            {
300                sb.append( " -Dclassifier=" );
301                sb.append( classifier );
302            }
303            sb.append( " -Dpackaging=" );
304            sb.append( type );
305            sb.append( " -Dfile=/path/to/file" );
306            sb.append( LS );
307
308            // If people want to deploy it
309            sb.append( LS );
310            sb.append( indentation );
311            sb.append( "Alternatively, if you host your own repository you can deploy the file there: " );
312            sb.append( LS );
313            sb.append( indentation );
314            sb.append( "    mvn deploy:deploy-file -DgroupId=" );
315            sb.append( groupId );
316            sb.append( " -DartifactId=" );
317            sb.append( artifactId );
318            sb.append( " -Dversion=" );
319            sb.append( version );
320
321            //insert classifier only if it was used in the artifact
322            if ( classifier != null && !classifier.equals( "" ) )
323            {
324                sb.append( " -Dclassifier=" );
325                sb.append( classifier );
326            }
327            sb.append( " -Dpackaging=" );
328            sb.append( type );
329            sb.append( " -Dfile=/path/to/file" );
330            sb.append( " -Durl=[url] -DrepositoryId=[id]" );
331            sb.append( LS );
332        }
333
334        sb.append( constructArtifactPath( path, indentation ) );
335        sb.append( LS );
336
337        return sb.toString();
338    }
339
340    public String getArtifactPath()
341    {
342        return path;
343    }
344}