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.Date;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Map.Entry;
30 import org.apache.commons.collections.CollectionUtils;
31 import org.apache.commons.collections.PredicateUtils;
32 import org.apache.commons.collections.functors.NotPredicate;
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.maven.archiva.common.utils.VersionUtil;
35 import org.apache.maven.archiva.database.ArchivaDAO;
36 import org.apache.maven.archiva.database.ArchivaDatabaseException;
37 import org.apache.maven.archiva.database.ObjectNotFoundException;
38 import org.apache.maven.archiva.database.constraints.ArtifactsRelatedConstraint;
39 import org.apache.maven.archiva.database.constraints.ProjectsByArtifactUsageConstraint;
40 import org.apache.maven.archiva.database.constraints.UniqueArtifactIdConstraint;
41 import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint;
42 import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint;
43 import org.apache.maven.archiva.database.updater.DatabaseUpdater;
44 import org.apache.maven.archiva.model.ArchivaArtifact;
45 import org.apache.maven.archiva.model.ArchivaProjectModel;
46 import org.apache.maven.archiva.model.Keys;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 * DefaultRepositoryBrowsing
54 * @plexus.component role="org.apache.maven.archiva.database.browsing.RepositoryBrowsing"
56 public class DefaultRepositoryBrowsing
57 implements RepositoryBrowsing
59 private Logger log = LoggerFactory.getLogger( DefaultRepositoryBrowsing.class );
62 * @plexus.requirement role-hint="jdo"
64 private ArchivaDAO dao;
67 * @plexus.requirement role-hint="jdo"
69 private DatabaseUpdater dbUpdater;
72 * @see RepositoryBrowsing#getRoot(String, List)
74 public BrowsingResults getRoot( final String principal, final List<String> observableRepositoryIds )
76 final BrowsingResults results = new BrowsingResults();
78 if ( !observableRepositoryIds.isEmpty() )
80 final List<String> groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds ) );
81 results.setSelectedRepositoryIds( observableRepositoryIds );
82 results.setGroupIds( GroupIdFilter.filterGroups( groups ) );
88 * @see RepositoryBrowsing#selectArtifactId(String, List, String, String)
90 public BrowsingResults selectArtifactId( final String principal, final List<String> observableRepositoryIds,
91 final String groupId, final String artifactId )
93 final BrowsingResults results = new BrowsingResults( groupId, artifactId );
95 if ( !observableRepositoryIds.isEmpty() )
97 // NOTE: No group Id or artifact Id's should be returned here.
98 List<String> versions =
99 dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) );
100 results.setSelectedRepositoryIds( observableRepositoryIds );
102 results.setVersions( processSnapshots( versions ) );
108 * @see RepositoryBrowsing#selectGroupId(String, List, String)
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 = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds, groupId ) );
118 final List<String> artifacts =
119 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.setGroupIds( groups );
126 results.setArtifacts( artifacts );
133 * @see RepositoryBrowsing#selectVersion(String, List, String, String, String)
135 public ArchivaProjectModel selectVersion( final String principal, final List<String> observableRepositoryIds,
136 final String groupId, final String artifactId, final String version )
137 throws ObjectNotFoundException, ArchivaDatabaseException
139 if ( observableRepositoryIds.isEmpty() )
141 throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal );
144 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() );
159 public String getRepositoryId( final String principal, final List<String> observableRepositoryIds,
160 final String groupId, final String artifactId, final String version )
161 throws ObjectNotFoundException, ArchivaDatabaseException
163 if ( observableRepositoryIds.isEmpty() )
165 throw new ArchivaDatabaseException( "There are no observable repositories for the user " + principal );
170 ArchivaArtifact pomArchivaArtifact =
171 getArtifact( principal, observableRepositoryIds, groupId, artifactId, version );
173 return pomArchivaArtifact.getModel().getRepositoryId();
175 catch ( ObjectNotFoundException e )
177 return getNoPomArtifactRepoId( principal, observableRepositoryIds, groupId, artifactId, version,
178 observableRepositoryIds.get( 0 ) );
183 * @see RepositoryBrowsing#getOtherSnapshotVersions(List, String, String, String)
185 public List<String> getOtherSnapshotVersions( List<String> observableRepositoryIds, String groupId,
186 String artifactId, String version )
187 throws ObjectNotFoundException, ArchivaDatabaseException
189 List<String> timestampedVersions = new ArrayList<String>();
191 if ( VersionUtil.isSnapshot( version ) )
193 List<String> versions =
194 dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) );
196 for ( String uniqueVersion : versions )
198 if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) ||
199 VersionUtil.getBaseVersion( uniqueVersion ).equals( VersionUtil.getBaseVersion( version ) ) )
201 if ( !timestampedVersions.contains( uniqueVersion ) )
203 timestampedVersions.add( uniqueVersion );
209 return timestampedVersions;
212 private ArchivaArtifact getArtifact( final String principal, final List<String> observableRepositoryIds,
213 final String groupId, final String artifactId, final String version )
214 throws ObjectNotFoundException, ArchivaDatabaseException
216 ArchivaArtifact pomArtifact = null;
218 for ( final String repositoryId : observableRepositoryIds )
223 dao.getArtifactDAO().getArtifact( groupId, artifactId, version, null, "pom", repositoryId );
226 catch ( ArchivaDatabaseException e )
228 pomArtifact = handleGenericSnapshots( groupId, artifactId, version, repositoryId );
232 if ( pomArtifact == null )
234 String type = getArtifactType( groupId, artifactId, version );
236 // We dont want these to persist in the database
238 new ArchivaArtifact( groupId, artifactId, version, null, type, observableRepositoryIds.get( 0 ) );
239 pomArtifact.getModel().setWhenProcessed( new Date() );
242 // Allowed to see this?
243 if ( observableRepositoryIds.contains( pomArtifact.getModel().getRepositoryId() ) )
249 throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) +
250 " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " ) +
251 "] for user " + principal );
255 public List<ArchivaProjectModel> getUsedBy( final String principal, final List<String> observableRepositoryIds,
256 final String groupId, final String artifactId, final String version )
257 throws ArchivaDatabaseException
259 ProjectsByArtifactUsageConstraint constraint =
260 new ProjectsByArtifactUsageConstraint( groupId, artifactId, version );
261 List<ArchivaProjectModel> results = dao.getProjectModelDAO().queryProjectModels( constraint );
262 if ( results == null )
264 // defensive. to honor contract as specified. never null.
265 return Collections.EMPTY_LIST;
272 * Removes SNAPSHOT versions with build numbers. Retains only the generic SNAPSHOT version.
273 * Example, if the list of versions are:
276 * - 2.1-20070522.143249-1
277 * - 2.1-20070522.157829-2
279 * the returned version list would contain 2.0, 2.0.1 and 2.1-SNAPSHOT.
283 private List<String> processSnapshots( List<String> versions )
285 List<String> cleansedVersions = new ArrayList<String>();
287 for ( String version : versions )
289 if ( VersionUtil.isSnapshot( version ) )
291 String baseVersion = VersionUtil.getBaseVersion( version );
292 if ( !cleansedVersions.contains( baseVersion ) )
294 cleansedVersions.add( baseVersion );
299 cleansedVersions.add( version );
303 return cleansedVersions;
307 * Handles querying of generic (*-SNAPSHOT) snapshot version. Process: - Get all the timestamped/unique versions of
308 * the artifact from the db - Sort the queried project models - Reverse the list of queried project models to get
309 * the latest timestamp version - Loop through the list and get the first one to match the generic (*-SNAPHOT)
316 * @throws ArchivaDatabaseException
318 private ArchivaArtifact handleGenericSnapshots( final String groupId, final String artifactId,
319 final String version, final String repositoryId )
320 throws ArchivaDatabaseException
322 ArchivaArtifact result = null;
324 if ( VersionUtil.isGenericSnapshot( version ) )
326 final List<String> versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) );
327 Collections.sort( versions );
328 Collections.reverse( versions );
330 for ( String uniqueVersion : versions )
332 if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) )
336 log.debug( "Retrieving artifact with version " + uniqueVersion );
338 dao.getArtifactDAO().getArtifact( groupId, artifactId, uniqueVersion, null, "pom", repositoryId );
341 catch ( ObjectNotFoundException e )
343 log.debug( "Artifact '" + groupId + ":" + artifactId + ":" + uniqueVersion +
344 "' in repository '" + repositoryId + "' not found in the database." );
354 * Get the project model from the database.
360 * @throws ArchivaDatabaseException
362 private ArchivaProjectModel getProjectModel( String groupId, String artifactId, String version )
363 throws ArchivaDatabaseException
365 ArchivaProjectModel model = null;
369 model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
371 catch ( ObjectNotFoundException e )
373 log.debug( "Unable to find project model for [" + Keys.toKey( groupId, artifactId, version ) + "]", e );
378 model = new ArchivaProjectModel();
379 model.setGroupId( groupId );
380 model.setArtifactId( artifactId );
381 model.setVersion( version );
387 private String getNoPomArtifactRepoId( String principal, List<String> observableRepos, String groupId,
388 String artifactId, String version, String repositoryId )
389 throws ObjectNotFoundException, ArchivaDatabaseException
391 ArchivaArtifact artifact = null;
393 String type = getArtifactType( groupId, artifactId, version );
395 artifact = dao.getArtifactDAO().createArtifact( groupId, artifactId, version, null, type, repositoryId );
397 if ( artifact == null )
399 // Lets not persist these
400 artifact = new ArchivaArtifact( groupId, artifactId, version, null, type, repositoryId );
403 // Allowed to see this?
404 if ( !observableRepos.contains( artifact.getModel().getRepositoryId() ) )
406 throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) +
407 " in observable repository [" + StringUtils.join( observableRepos.iterator(), ", " ) + "] for user " +
411 return artifact.getModel().getRepositoryId();
414 private String getArtifactType( String groupId, String artifactId, String version )
415 throws ObjectNotFoundException, ArchivaDatabaseException
421 List<ArchivaArtifact> artifacts =
422 dao.getArtifactDAO().queryArtifacts( new ArtifactsRelatedConstraint( groupId, artifactId, version ) );
424 if ( artifacts.size() > 0 )
426 type = artifacts.get( 0 ).getType();
429 catch ( ObjectNotFoundException e )
431 // swallow exception?