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( "  " + groupId + ":" + artifactId + ":" + type + ":" + version );
203            sb.append( LS );
204            if ( remoteRepositories != null )
205            {
206                sb.append( LS );
207                sb.append( "from the specified remote repositories:" );
208                sb.append( LS + "  " );
209
210                if ( remoteRepositories.isEmpty() )
211                {
212                    sb.append( "(none)" );
213                }
214
215                for ( Iterator<ArtifactRepository> i = remoteRepositories.iterator(); i.hasNext(); )
216                {
217                    ArtifactRepository remoteRepository = i.next();
218
219                    sb.append( remoteRepository.getId() );
220                    sb.append( " (" );
221                    sb.append( remoteRepository.getUrl() );
222
223                    ArtifactRepositoryPolicy releases = remoteRepository.getReleases();
224                    if ( releases != null )
225                    {
226                        sb.append( ", releases=" ).append( releases.isEnabled() );
227                    }
228
229                    ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots();
230                    if ( snapshots != null )
231                    {
232                        sb.append( ", snapshots=" ).append( snapshots.isEnabled() );
233                    }
234
235                    sb.append( ")" );
236                    if ( i.hasNext() )
237                    {
238                        sb.append( "," ).append( LS ).append( "  " );
239                    }
240                }
241            }
242
243            sb.append( constructArtifactPath( path, "" ) );
244            sb.append( LS );
245        }
246
247        return sb.toString();
248    }
249
250    protected static String constructMissingArtifactMessage( String message,
251                                                             String indentation,
252                                                             String groupId,
253                                                             String artifactId,
254                                                             String version,
255                                                             String type,
256                                                             String classifier,
257                                                             String downloadUrl,
258                                                             List<String> path )
259    {
260        StringBuilder sb = new StringBuilder( message );
261
262        if ( !"pom".equals( type ) )
263        {
264            if ( downloadUrl != null )
265            {
266                sb.append( LS );
267                sb.append( LS );
268                sb.append( indentation );
269                sb.append( "Try downloading the file manually from: " );
270                sb.append( LS );
271                sb.append( indentation );
272                sb.append( "    " );
273                sb.append( downloadUrl );
274            }
275            else
276            {
277                sb.append( LS );
278                sb.append( LS );
279                sb.append( indentation );
280                sb.append( "Try downloading the file manually from the project website." );
281            }
282
283            sb.append( LS );
284            sb.append( LS );
285            sb.append( indentation );
286            sb.append( "Then, install it using the command: " );
287            sb.append( LS );
288            sb.append( indentation );
289            sb.append( "    mvn install:install-file -DgroupId=" );
290            sb.append( groupId );
291            sb.append( " -DartifactId=" );
292            sb.append( artifactId );
293            sb.append( " -Dversion=" );
294            sb.append( version );
295
296            //insert classifier only if it was used in the artifact
297            if ( classifier != null && !classifier.equals( "" ) )
298            {
299                sb.append( " -Dclassifier=" );
300                sb.append( classifier );
301            }
302            sb.append( " -Dpackaging=" );
303            sb.append( type );
304            sb.append( " -Dfile=/path/to/file" );
305            sb.append( LS );
306
307            // If people want to deploy it
308            sb.append( LS );
309            sb.append( indentation );
310            sb.append( "Alternatively, if you host your own repository you can deploy the file there: " );
311            sb.append( LS );
312            sb.append( indentation );
313            sb.append( "    mvn deploy:deploy-file -DgroupId=" );
314            sb.append( groupId );
315            sb.append( " -DartifactId=" );
316            sb.append( artifactId );
317            sb.append( " -Dversion=" );
318            sb.append( version );
319
320            //insert classifier only if it was used in the artifact
321            if ( classifier != null && !classifier.equals( "" ) )
322            {
323                sb.append( " -Dclassifier=" );
324                sb.append( classifier );
325            }
326            sb.append( " -Dpackaging=" );
327            sb.append( type );
328            sb.append( " -Dfile=/path/to/file" );
329            sb.append( " -Durl=[url] -DrepositoryId=[id]" );
330            sb.append( LS );
331        }
332
333        sb.append( constructArtifactPath( path, indentation ) );
334        sb.append( LS );
335
336        return sb.toString();
337    }
338
339    public String getArtifactPath()
340    {
341        return path;
342    }
343}