]> source.dussan.org Git - archiva.git/blob
bab71b036df219f6ba189c236aaa55c208d8f7dc
[archiva.git] /
1 package org.apache.maven.archiva.database.browsing;
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.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import org.apache.commons.collections.CollectionUtils;
29 import org.apache.commons.collections.PredicateUtils;
30 import org.apache.commons.collections.functors.NotPredicate;
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.maven.archiva.common.utils.VersionUtil;
33 import org.apache.maven.archiva.database.ArchivaDAO;
34 import org.apache.maven.archiva.database.ArchivaDatabaseException;
35 import org.apache.maven.archiva.database.ObjectNotFoundException;
36 import org.apache.maven.archiva.database.constraints.ProjectsByArtifactUsageConstraint;
37 import org.apache.maven.archiva.database.constraints.UniqueArtifactIdConstraint;
38 import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint;
39 import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint;
40 import org.apache.maven.archiva.database.updater.DatabaseUpdater;
41 import org.apache.maven.archiva.model.ArchivaArtifact;
42 import org.apache.maven.archiva.model.ArchivaProjectModel;
43 import org.apache.maven.archiva.model.Keys;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * DefaultRepositoryBrowsing
49  *
50  * @version $Id$
51  * @plexus.component role="org.apache.maven.archiva.database.browsing.RepositoryBrowsing"
52  */
53 public class DefaultRepositoryBrowsing
54     implements RepositoryBrowsing
55 {
56     private Logger log = LoggerFactory.getLogger( DefaultRepositoryBrowsing.class );
57     
58     /**
59      * @plexus.requirement role-hint="jdo"
60      */
61     private ArchivaDAO dao;
62
63     /**
64      * @plexus.requirement role-hint="jdo"
65      */
66     private DatabaseUpdater dbUpdater;
67
68     public BrowsingResults getRoot( final String principle, final List<String> observableRepositoryIds )
69     {
70         List<String> groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds ) );
71
72         BrowsingResults results = new BrowsingResults();
73         results.setSelectedRepositoryIds( observableRepositoryIds );
74
75         results.setGroupIds( GroupIdFilter.filterGroups( groups ) );
76
77         return results;
78     }
79
80     public BrowsingResults selectArtifactId( final String principle, final List<String> observableRepositoryIds, final String groupId,
81                                              final String artifactId )
82     {
83         // NOTE: No group Id or artifact Id's should be returned here. 
84         List<String> versions = dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) );
85
86         BrowsingResults results = new BrowsingResults( groupId, artifactId );
87         results.setSelectedRepositoryIds( observableRepositoryIds );
88
89         processSnapshots( versions );
90
91         results.setVersions( versions );
92
93         return results;
94     }
95
96     public BrowsingResults selectGroupId( final String principle, final List<String> observableRepositoryIds, final String groupId )
97     {
98         List<String> groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds, groupId ) );
99         List<String> artifacts = dao.query( new UniqueArtifactIdConstraint( observableRepositoryIds, groupId ) );
100
101         BrowsingResults results = new BrowsingResults( groupId );
102
103         // Remove searched for groupId from groups list.
104         // Easier to do this here, vs doing it in the SQL query.
105         CollectionUtils.filter( groups, NotPredicate.getInstance( PredicateUtils.equalPredicate( groupId ) ) );
106
107         results.setGroupIds( groups );
108         results.setArtifacts( artifacts );
109
110         return results;
111     }
112
113     public ArchivaProjectModel selectVersion( final String principle, final List<String> observableRepositoryIds, final String groupId,
114                                               final String artifactId, final String version )
115         throws ObjectNotFoundException, ArchivaDatabaseException
116     {
117         ArchivaArtifact pomArtifact = getArtifact( principle, observableRepositoryIds, groupId, artifactId, version );
118
119         ArchivaProjectModel model;
120
121         if ( !pomArtifact.getModel().isProcessed() )
122         {
123             // Process it.
124             dbUpdater.updateUnprocessed( pomArtifact );
125         }
126
127         model = getProjectModel( groupId, artifactId, pomArtifact.getVersion() );
128
129         return model;
130     }
131     
132     public String getRepositoryId( final String principle, final List<String> observableRepositoryIds, final String groupId,
133                                    final String artifactId, final String version )
134         throws ObjectNotFoundException, ArchivaDatabaseException
135     {
136         ArchivaArtifact pomArchivaArtifact =
137             getArtifact( principle, observableRepositoryIds, groupId, artifactId, version );
138
139         return pomArchivaArtifact.getModel().getRepositoryId();
140     }
141     
142     private ArchivaArtifact getArtifact( final String principal, final List<String> observableRepositoryIds, final String groupId,
143                                          final String artifactId, final String version )
144         throws ObjectNotFoundException, ArchivaDatabaseException
145     {
146         ArchivaArtifact pomArtifact = null;
147
148         for (final String repositoryId : observableRepositoryIds)
149         {
150             try
151             {
152                 pomArtifact = dao.getArtifactDAO().getArtifact( groupId, artifactId, version, null, "pom", repositoryId );
153             }
154             catch ( ObjectNotFoundException e )
155             {
156                 pomArtifact = handleGenericSnapshots( groupId, artifactId, version, repositoryId );
157             }
158         }
159
160
161         if ( pomArtifact == null )
162         {
163             throw new ObjectNotFoundException( "Unable to find artifact [" + Keys.toKey( groupId, artifactId, version )
164                 + "]" );
165         }
166
167         // Allowed to see this?
168         if ( observableRepositoryIds.contains( pomArtifact.getModel().getRepositoryId() ) )
169         {
170             return pomArtifact;
171         }
172         else
173         {
174             throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version )
175                 + " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " )
176                 + "] for user " + principal );
177         }
178     }
179
180     public List<ArchivaProjectModel> getUsedBy( final String principle, final List<String> observableRepositoryIds, final String groupId,
181                                                 final String artifactId, final String version )
182         throws ArchivaDatabaseException
183     {
184         ProjectsByArtifactUsageConstraint constraint = new ProjectsByArtifactUsageConstraint( groupId, artifactId,
185                                                                                               version );
186         List<ArchivaProjectModel> results = dao.getProjectModelDAO().queryProjectModels( constraint );
187         if ( results == null )
188         {
189             // defensive. to honor contract as specified. never null.
190             return Collections.EMPTY_LIST;
191         }
192
193         return results;
194     }
195
196     /**
197      * Add generic (*-SNAPSHOT) snapshot versions in the list for artifacts with only unique version (timestamped)
198      * snapshots.
199      * <p/>
200      * Ex.
201      * artifact1 has the ff. versions retrieved from the db:
202      * - 1.0
203      * - 1.1-20061118.060401-2
204      * - 1.1-20061118.060402-3
205      * - 2.2-20071007.070101-1
206      * - 2.2-20071007.070110-2
207      * - 2.2-SNAPSHOT
208      * <p/>
209      * This method will add a '1.1-SNAPSHOT' in the list since there is no generic snapshot entry for it.
210      * When this version is browsed, the pom of the latest snapshot will be displayed.
211      *
212      * @param versions
213      */
214     private void processSnapshots( final List<String> versions )
215     {
216         Map<String, String> snapshots = new HashMap<String, String>();
217
218         for ( String version : versions )
219         {
220             if ( VersionUtil.isSnapshot( version ) )
221             {
222                 String baseVersion = VersionUtil.getBaseVersion( version );
223                 if ( !snapshots.containsKey( baseVersion ) )
224                 {
225                     snapshots.put( baseVersion, baseVersion );
226                 }
227             }
228         }
229
230         for ( Entry<String, String> entry : snapshots.entrySet() )
231         {
232             String baseVersion = entry.getValue();
233             if ( !versions.contains( baseVersion ) )
234             {
235                 versions.add( baseVersion );
236             }
237         }
238     }
239
240     /**
241      * Handles querying of generic (*-SNAPSHOT) snapshot version.
242      * Process:
243      * - Get all the timestamped/unique versions of the artifact from the db
244      * - Sort the queried project models
245      * - Reverse the list of queried project models to get the latest timestamp version
246      * - Loop through the list and get the first one to match the generic (*-SNAPHOT) version
247      *
248      * @param groupId
249      * @param artifactId
250      * @param version
251      * @param pomArtifact
252      * @throws ArchivaDatabaseException
253      */
254     private ArchivaArtifact handleGenericSnapshots( final String groupId, final String artifactId, final String version, final String repositoryId )
255         throws ArchivaDatabaseException
256     {
257         ArchivaArtifact result = null;
258
259         if ( VersionUtil.isGenericSnapshot( version ) )
260         {
261             List<String> versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) );
262             Collections.sort( versions );
263             Collections.reverse( versions );
264
265             for ( String uniqueVersion : versions )
266             {
267                 if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) )
268                 {
269                     log.info( "Retrieving artifact with version " + uniqueVersion );
270                     result = dao.getArtifactDAO().getArtifact( groupId, artifactId, uniqueVersion, null, "pom", repositoryId );
271                 }
272             }
273         }
274         return result;
275     }
276
277     /**
278      * Get the project model from the database.
279      *
280      * @param groupId
281      * @param artifactId
282      * @param version
283      * @return
284      * @throws ArchivaDatabaseException
285      */
286     private ArchivaProjectModel getProjectModel( String groupId, String artifactId, String version )
287         throws ArchivaDatabaseException
288     {
289         try
290         {
291             ArchivaProjectModel model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
292
293             if ( model == null )
294             {
295                 throw new ObjectNotFoundException( "Unable to find project model for ["
296                     + Keys.toKey( groupId, artifactId, version ) + "]" );
297             }
298
299             return model;
300         }
301         catch ( ObjectNotFoundException e )
302         {
303             throw e;
304         }
305     }
306     
307 }