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