1 package org.apache.archiva.rest.services;
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import net.sf.beanlib.provider.replicator.BeanReplicator;
22 import org.apache.archiva.indexer.search.RepositorySearch;
23 import org.apache.archiva.indexer.search.RepositorySearchException;
24 import org.apache.archiva.indexer.search.SearchFields;
25 import org.apache.archiva.indexer.search.SearchResultHit;
26 import org.apache.archiva.indexer.search.SearchResultLimits;
27 import org.apache.archiva.indexer.search.SearchResults;
28 import org.apache.archiva.rest.api.model.Artifact;
29 import org.apache.archiva.rest.api.model.Dependency;
30 import org.apache.archiva.rest.api.model.SearchRequest;
31 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
32 import org.apache.archiva.rest.api.services.SearchService;
33 import org.apache.archiva.rest.services.interceptors.HttpContext;
34 import org.apache.archiva.rest.services.interceptors.HttpContextThreadLocal;
35 import org.apache.archiva.security.AccessDeniedException;
36 import org.apache.archiva.security.ArchivaSecurityException;
37 import org.apache.archiva.security.PrincipalNotFoundException;
38 import org.apache.archiva.security.UserRepositories;
39 import org.apache.commons.lang.StringUtils;
40 import org.codehaus.plexus.redback.users.UserManager;
41 import org.codehaus.redback.rest.services.RedbackAuthenticationThreadLocal;
42 import org.codehaus.redback.rest.services.RedbackRequestInformation;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.stereotype.Service;
47 import javax.inject.Inject;
48 import javax.servlet.http.HttpServletRequest;
49 import java.util.ArrayList;
50 import java.util.Collections;
51 import java.util.List;
54 * @author Olivier Lamy
56 @Service( "searchService#rest" )
57 public class DefaultSearchService
58 implements SearchService
61 private Logger log = LoggerFactory.getLogger( getClass() );
64 private RepositorySearch repositorySearch;
67 private UserRepositories userRepositories;
69 public List<Artifact> quickSearch( String queryString )
70 throws ArchivaRestServiceException
72 if ( StringUtils.isBlank( queryString ) )
74 return Collections.emptyList();
77 SearchResultLimits limits = new SearchResultLimits( 0 );
78 List<String> observableRepoIds = getObservableRepos();
81 SearchResults searchResults =
82 repositorySearch.search( getPrincipal(), getObservableRepos(), queryString, limits,
83 Collections.<String>emptyList() );
84 return getArtifacts( searchResults );
87 catch ( RepositorySearchException e )
89 log.error( e.getMessage(), e );
90 throw new ArchivaRestServiceException( e.getMessage() );
94 public List<Artifact> getArtifactVersions( String groupId, String artifactId, String packaging )
95 throws ArchivaRestServiceException
97 if ( StringUtils.isBlank( groupId ) || StringUtils.isBlank( artifactId ) )
99 return Collections.emptyList();
101 SearchFields searchField = new SearchFields();
102 searchField.setGroupId( groupId );
103 searchField.setArtifactId( artifactId );
104 searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
108 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
109 return getArtifacts( searchResults );
111 catch ( RepositorySearchException e )
113 log.error( e.getMessage(), e );
114 throw new ArchivaRestServiceException( e.getMessage() );
118 public List<Artifact> searchArtifacts( SearchRequest searchRequest )
119 throws ArchivaRestServiceException
121 if ( searchRequest == null )
123 return Collections.emptyList();
125 SearchFields searchField = new BeanReplicator().replicateBean( searchRequest, SearchFields.class );
126 SearchResultLimits limits = new SearchResultLimits( 0 );
130 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, limits );
131 return getArtifacts( searchResults );
133 catch ( RepositorySearchException e )
135 log.error( e.getMessage(), e );
136 throw new ArchivaRestServiceException( e.getMessage() );
140 public List<Dependency> getDependencies( String groupId, String artifactId, String version )
141 throws ArchivaRestServiceException
143 return null; //To change body of implemented methods use File | Settings | File Templates.
146 public List<Artifact> getArtifactByChecksum( String checksum )
147 throws ArchivaRestServiceException
149 return null; //To change body of implemented methods use File | Settings | File Templates.
153 protected List<String> getObservableRepos()
157 List<String> ids = userRepositories.getObservableRepositoryIds( getPrincipal() );
158 return ids == null ? Collections.<String>emptyList() : ids;
160 catch ( PrincipalNotFoundException e )
162 log.warn( e.getMessage(), e );
164 catch ( AccessDeniedException e )
166 log.warn( e.getMessage(), e );
168 catch ( ArchivaSecurityException e )
170 log.warn( e.getMessage(), e );
172 return Collections.emptyList();
175 protected String getPrincipal()
177 RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
179 return redbackRequestInformation == null
180 ? UserManager.GUEST_USERNAME
181 : ( redbackRequestInformation.getUser() == null
182 ? UserManager.GUEST_USERNAME
183 : redbackRequestInformation.getUser().getUsername() );
186 protected List<Artifact> getArtifacts( SearchResults searchResults )
189 HttpContext httpContext = HttpContextThreadLocal.get();
190 if ( searchResults == null || searchResults.isEmpty() )
192 return Collections.emptyList();
194 List<Artifact> artifacts = new ArrayList<Artifact>( searchResults.getReturnedHitsCount() );
195 for ( SearchResultHit hit : searchResults.getHits() )
197 // duplicate Artifact one per available version
198 if ( hit.getVersions().size() > 0 )
200 for ( String version : hit.getVersions() )
203 Artifact versionned = new Artifact( );
204 versionned.setArtifactId( hit.getArtifactId());
205 versionned.setGroupId( hit.getGroupId() );
206 versionned.setRepositoryId(hit.getRepositoryId() );
209 versionned.setBundleExportPackage( hit.getBundleExportPackage() );
210 versionned.setBundleExportService( hit.getBundleExportService());
211 versionned.setBundleSymbolicName(hit.getBundleSymbolicName() );
212 versionned.setBundleVersion( artifactInfo.bundleVersion );
213 versionned.setBundleDescription( artifactInfo.bundleDescription );
214 versionned.setBundleDocUrl( artifactInfo.bundleDocUrl );
216 versionned.setBundleRequireBundle( artifactInfo.bundleRequireBundle );
217 versionned.setBundleImportPackage( artifactInfo.bundleImportPackage );
218 versionned.setBundleLicense( artifactInfo.bundleLicense );
219 versionned.setBundleName( artifactInfo.bundleName );
220 versionned.setContext( artifactInfo.context );
221 versionned.setGoals( artifactInfo.goals );
222 versionned.setPrefix( artifactInfo.prefix );
224 versionned.setUrl( artifactInfo.remoteUrl );
226 // FIXME archiva url ??
228 Artifact versionned = new BeanReplicator().replicateBean( hit, Artifact.class );
230 if ( StringUtils.isNotBlank( version ) )
232 versionned.setVersion( version );
233 versionned.setUrl( getArtifactUrl( httpContext, versionned ) );
235 artifacts.add( versionned );
244 private String getArtifactUrl( HttpContext httpContext, Artifact artifact )
246 if ( httpContext == null )
250 if ( httpContext.getHttpServletRequest() == null )
254 StringBuilder sb = new StringBuilder( getBaseUrl( httpContext.getHttpServletRequest() ) );
256 sb.append( "/repository" );
258 if ( StringUtils.startsWith( artifact.getContext(), "remote-" ) )
260 // if context is 'remote-*' we have to set a repo which the current user can use
264 sb.append( '/' ).append( artifact.getContext() );
267 sb.append( '/' ).append( StringUtils.replaceChars( artifact.getGroupId(), '.', '/' ) );
268 sb.append( '/' ).append( artifact.getArtifactId() );
269 sb.append( '/' ).append( artifact.getVersion() );
270 sb.append( '/' ).append( artifact.getArtifactId() );
271 if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
273 sb.append( '-' ).append( artifact.getClassifier() );
275 sb.append( '-' ).append( artifact.getVersion() );
276 sb.append( '.' ).append( artifact.getPackaging() );
278 return sb.toString();
281 protected String getBaseUrl( HttpServletRequest req )
283 return req.getScheme() + "://" + req.getServerName()
284 + ( req.getServerPort() == 80 ? "" : ":" + req.getServerPort() ) + req.getContextPath();