1 package org.apache.maven.archiva.database.browsing;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
26 import org.apache.commons.collections.CollectionUtils;
27 import org.apache.commons.collections.PredicateUtils;
28 import org.apache.commons.collections.functors.NotPredicate;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.maven.archiva.common.utils.VersionUtil;
31 import org.apache.maven.archiva.database.ArchivaDAO;
32 import org.apache.maven.archiva.database.ArchivaDatabaseException;
33 import org.apache.maven.archiva.database.Constraint;
34 import org.apache.maven.archiva.database.ObjectNotFoundException;
35 import org.apache.maven.archiva.database.constraints.ArtifactsRelatedConstraint;
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;
48 * DefaultRepositoryBrowsing
51 * @plexus.component role="org.apache.maven.archiva.database.browsing.RepositoryBrowsing"
53 public class DefaultRepositoryBrowsing
54 implements RepositoryBrowsing
56 private Logger log = LoggerFactory.getLogger( DefaultRepositoryBrowsing.class );
59 * @plexus.requirement role-hint="jdo"
61 private ArchivaDAO dao;
64 * @plexus.requirement role-hint="jdo"
66 private DatabaseUpdater dbUpdater;
69 * @see RepositoryBrowsing#getRoot(String, List)
71 @SuppressWarnings("unchecked")
72 public BrowsingResults getRoot( final String principal, final List<String> observableRepositoryIds )
74 final BrowsingResults results = new BrowsingResults();
76 if ( !observableRepositoryIds.isEmpty() )
78 final List<String> groups = (List<String>) dao.query( new UniqueGroupIdConstraint( observableRepositoryIds ) );
79 results.setSelectedRepositoryIds( observableRepositoryIds );
80 results.setGroupIds( GroupIdFilter.filterGroups( groups ) );
86 * @see RepositoryBrowsing#selectArtifactId(String, List, String, String)
88 @SuppressWarnings("unchecked")
89 public BrowsingResults selectArtifactId( final String principal, final List<String> observableRepositoryIds,
90 final String groupId, final String artifactId )
92 final BrowsingResults results = new BrowsingResults( groupId, artifactId );
94 if ( !observableRepositoryIds.isEmpty() )
96 // NOTE: No group Id or artifact Id's should be returned here.
97 List<String> versions =
98 (List<String>) dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) );
99 results.setSelectedRepositoryIds( observableRepositoryIds );
101 results.setVersions( processSnapshots( versions ) );
107 * @see RepositoryBrowsing#selectGroupId(String, List, String)
109 @SuppressWarnings("unchecked")
110 public BrowsingResults selectGroupId( final String principal, final List<String> observableRepositoryIds,
111 final String groupId )
113 final BrowsingResults results = new BrowsingResults( groupId );
115 if ( !observableRepositoryIds.isEmpty() )
117 final List<String> groups = (List<String>) dao.query( new UniqueGroupIdConstraint( observableRepositoryIds, groupId ) );
118 final List<String> artifacts =
119 (List<String>) dao.query( new UniqueArtifactIdConstraint( observableRepositoryIds, groupId ) );
121 // Remove searched for groupId from groups list.
122 // Easier to do this here, vs doing it in the SQL query.
123 CollectionUtils.filter( groups, NotPredicate.getInstance( PredicateUtils.equalPredicate( groupId ) ) );
125 results.setSelectedRepositoryIds( observableRepositoryIds );
126 results.setGroupIds( groups );
127 results.setArtifacts( artifacts );
134 * @see RepositoryBrowsing#selectVersion(String, List, String, String, String)
136 public ArchivaProjectModel selectVersion( final String principal, final List<String> observableRepositoryIds,
137 final String groupId, final String artifactId, final String version )
138 throws ObjectNotFoundException, ArchivaDatabaseException
140 if ( observableRepositoryIds.isEmpty() )
142 throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal );
145 ArchivaArtifact pomArtifact = getArtifact( principal, observableRepositoryIds, groupId, artifactId, version );
146 ArchivaProjectModel model;
148 if ( !pomArtifact.getModel().isProcessed() )
151 dbUpdater.updateUnprocessed( pomArtifact );
154 model = getProjectModel( groupId, artifactId, pomArtifact.getVersion() );
156 if ( model.getPackaging() == null || "".equals( model.getPackaging() ) )
158 model.setPackaging( pomArtifact.getType() );
164 public String getRepositoryId( final String principal, final List<String> observableRepositoryIds,
165 final String groupId, final String artifactId, final String version )
166 throws ObjectNotFoundException, ArchivaDatabaseException
168 if ( observableRepositoryIds.isEmpty() )
170 throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal );
175 ArchivaArtifact pomArchivaArtifact =
176 getArtifact( principal, observableRepositoryIds, groupId, artifactId, version );
178 return pomArchivaArtifact.getModel().getRepositoryId();
180 catch ( ObjectNotFoundException e )
182 return getNoPomArtifactRepoId( principal, observableRepositoryIds, groupId, artifactId, version,
183 observableRepositoryIds.get( 0 ) );
188 * @see RepositoryBrowsing#getOtherSnapshotVersions(List, String, String, String)
190 @SuppressWarnings("unchecked")
191 public List<String> getOtherSnapshotVersions( List<String> observableRepositoryIds, String groupId,
192 String artifactId, String version )
193 throws ObjectNotFoundException, ArchivaDatabaseException
195 List<String> timestampedVersions = new ArrayList<String>();
197 if ( VersionUtil.isSnapshot( version ) )
199 List<String> versions =
200 (List<String>) dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) );
202 for ( String uniqueVersion : versions )
204 if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) ||
205 VersionUtil.getBaseVersion( uniqueVersion ).equals( VersionUtil.getBaseVersion( version ) ) )
207 if ( !timestampedVersions.contains( uniqueVersion ) )
209 timestampedVersions.add( uniqueVersion );
215 return timestampedVersions;
218 private ArchivaArtifact getArtifact( final String principal, final List<String> observableRepositoryIds,
219 final String groupId, final String artifactId, final String version )
220 throws ObjectNotFoundException, ArchivaDatabaseException
222 ArchivaArtifact pomArtifact = null;
223 Constraint constraint = new ArtifactsRelatedConstraint( groupId, artifactId, version );
227 List<ArchivaArtifact> artifacts = dao.getArtifactDAO().queryArtifacts( constraint );
229 // it's possible that similar artifacts reside in different repos
230 if ( !artifacts.isEmpty() )
232 for ( ArchivaArtifact artifact : artifacts )
234 if ( observableRepositoryIds.contains( artifact.getRepositoryId() ) )
236 pomArtifact = artifact;
242 catch ( ArchivaDatabaseException e )
244 log.warn( "ArchivaDatabaseException occurred while querying for artifact '" + groupId + ":" + artifactId +
245 ":" + version + "'." );
248 if ( pomArtifact == null )
250 for ( final String repositoryId : observableRepositoryIds )
252 pomArtifact = handleGenericSnapshots( groupId, artifactId, version, repositoryId );
254 if ( pomArtifact != null )
261 // throw exception if pom artifact is still null!
262 if ( pomArtifact == null )
264 throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) +
265 " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " ) +
266 "] for user " + principal );
272 public List<ArchivaProjectModel> getUsedBy( final String principal, final List<String> observableRepositoryIds,
273 final String groupId, final String artifactId, final String version )
274 throws ArchivaDatabaseException
276 ProjectsByArtifactUsageConstraint constraint =
277 new ProjectsByArtifactUsageConstraint( groupId, artifactId, version );
278 List<ArchivaProjectModel> results = dao.getProjectModelDAO().queryProjectModels( constraint );
279 if ( results == null )
281 // defensive. to honor contract as specified. never null.
282 return Collections.emptyList();
289 * Removes SNAPSHOT versions with build numbers. Retains only the generic SNAPSHOT version.
290 * Example, if the list of versions are:
293 * - 2.1-20070522.143249-1
294 * - 2.1-20070522.157829-2
296 * the returned version list would contain 2.0, 2.0.1 and 2.1-SNAPSHOT.
300 private List<String> processSnapshots( List<String> versions )
302 List<String> cleansedVersions = new ArrayList<String>();
304 for ( String version : versions )
306 if ( VersionUtil.isSnapshot( version ) )
308 String baseVersion = VersionUtil.getBaseVersion( version );
309 if ( !cleansedVersions.contains( baseVersion ) )
311 cleansedVersions.add( baseVersion );
316 cleansedVersions.add( version );
320 return cleansedVersions;
324 * Handles querying of generic (*-SNAPSHOT) snapshot version. Process: - Get all the timestamped/unique versions of
325 * the artifact from the db - Sort the queried project models - Reverse the list of queried project models to get
326 * the latest timestamp version - Loop through the list and get the first one to match the generic (*-SNAPHOT)
333 * @throws ArchivaDatabaseException
335 @SuppressWarnings("unchecked")
336 private ArchivaArtifact handleGenericSnapshots( final String groupId, final String artifactId,
337 final String version, final String repositoryId )
338 throws ArchivaDatabaseException
340 ArchivaArtifact result = null;
342 if ( VersionUtil.isGenericSnapshot( version ) )
344 final List<String> versions = (List<String>) dao.query( new UniqueVersionConstraint( groupId, artifactId ) );
345 Collections.sort( versions );
346 Collections.reverse( versions );
348 for ( String uniqueVersion : versions )
350 if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) )
354 log.debug( "Retrieving artifact with version " + uniqueVersion );
355 Constraint constraint = new ArtifactsRelatedConstraint( groupId, artifactId, uniqueVersion );
356 List<ArchivaArtifact> artifacts = dao.getArtifactDAO().queryArtifacts( constraint );
358 for ( ArchivaArtifact artifact : artifacts )
360 if ( artifact.getRepositoryId().equals( repositoryId ) )
367 catch ( ObjectNotFoundException e )
369 log.debug( "Artifact '" + groupId + ":" + artifactId + ":" + uniqueVersion +
370 "' in repository '" + repositoryId + "' not found in the database." );
380 * Get the project model from the database.
386 * @throws ArchivaDatabaseException
388 private ArchivaProjectModel getProjectModel( String groupId, String artifactId, String version )
389 throws ArchivaDatabaseException
391 ArchivaProjectModel model = null;
395 model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
397 catch ( ObjectNotFoundException e )
399 log.debug( "Unable to find project model for [" + Keys.toKey( groupId, artifactId, version ) + "]", e );
404 model = new ArchivaProjectModel();
405 model.setGroupId( groupId );
406 model.setArtifactId( artifactId );
407 model.setVersion( version );
413 private String getNoPomArtifactRepoId( String principal, List<String> observableRepos, String groupId,
414 String artifactId, String version, String repositoryId )
415 throws ObjectNotFoundException, ArchivaDatabaseException
417 ArchivaArtifact artifact = null;
419 String type = getArtifactType( groupId, artifactId, version );
421 artifact = dao.getArtifactDAO().createArtifact( groupId, artifactId, version, null, type, repositoryId );
423 if ( artifact == null )
425 // Lets not persist these
426 artifact = new ArchivaArtifact( groupId, artifactId, version, null, type, repositoryId );
429 // Allowed to see this?
430 if ( !observableRepos.contains( artifact.getModel().getRepositoryId() ) )
432 throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) +
433 " in observable repository [" + StringUtils.join( observableRepos.iterator(), ", " ) + "] for user " +
437 return artifact.getModel().getRepositoryId();
440 private String getArtifactType( String groupId, String artifactId, String version )
441 throws ObjectNotFoundException, ArchivaDatabaseException
447 List<ArchivaArtifact> artifacts =
448 dao.getArtifactDAO().queryArtifacts( new ArtifactsRelatedConstraint( groupId, artifactId, version ) );
450 if ( artifacts.size() > 0 )
452 type = artifacts.get( 0 ).getType();
455 catch ( ObjectNotFoundException e )
457 // swallow exception?