1 package org.apache.archiva.rest.services;
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 org.apache.archiva.admin.model.beans.ProxyConnector;
23 import org.apache.archiva.indexer.search.RepositorySearch;
24 import org.apache.archiva.indexer.search.RepositorySearchException;
25 import org.apache.archiva.indexer.search.SearchFields;
26 import org.apache.archiva.indexer.search.SearchResultHit;
27 import org.apache.archiva.indexer.search.SearchResultLimits;
28 import org.apache.archiva.indexer.search.SearchResults;
29 import org.apache.archiva.maven2.model.Artifact;
30 import org.apache.archiva.rest.api.model.Dependency;
31 import org.apache.archiva.rest.api.model.GroupIdList;
32 import org.apache.archiva.rest.api.model.SearchRequest;
33 import org.apache.archiva.rest.api.model.StringList;
34 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
35 import org.apache.archiva.rest.api.services.SearchService;
36 import org.apache.commons.collections.ListUtils;
37 import org.apache.commons.lang.StringUtils;
38 import org.springframework.stereotype.Service;
40 import javax.inject.Inject;
41 import javax.ws.rs.core.Response;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.List;
50 * @author Olivier Lamy
52 @Service("searchService#rest")
53 public class DefaultSearchService
54 extends AbstractRestService
55 implements SearchService
59 private RepositorySearch repositorySearch;
62 public List<Artifact> quickSearch( String queryString )
63 throws ArchivaRestServiceException
65 if ( StringUtils.isBlank( queryString ) )
67 return Collections.emptyList();
70 SearchResultLimits limits = new SearchResultLimits( 0 );
73 SearchResults searchResults =
74 repositorySearch.search( getPrincipal(), getObservableRepos(), queryString, limits,
75 Collections.<String>emptyList() );
76 return getArtifacts( searchResults );
79 catch ( RepositorySearchException e )
81 log.error( e.getMessage(), e );
82 throw new ArchivaRestServiceException( e.getMessage(), e );
87 public List<Artifact> quickSearchWithRepositories( SearchRequest searchRequest )
88 throws ArchivaRestServiceException
90 String queryString = searchRequest.getQueryTerms();
91 if ( StringUtils.isBlank( queryString ) )
93 return Collections.emptyList();
95 List<String> repositories = searchRequest.getRepositories();
96 if ( repositories == null || repositories.isEmpty() )
98 repositories = getObservableRepos();
100 SearchResultLimits limits =
101 new SearchResultLimits( searchRequest.getPageSize(), searchRequest.getSelectedPage() );
104 SearchResults searchResults = repositorySearch.search( getPrincipal(), repositories, queryString, limits,
105 Collections.<String>emptyList() );
106 return getArtifacts( searchResults );
109 catch ( RepositorySearchException e )
111 log.error( e.getMessage(), e );
112 throw new ArchivaRestServiceException( e.getMessage(), e );
117 public List<Artifact> getArtifactVersions( String groupId, String artifactId, String packaging )
118 throws ArchivaRestServiceException
120 if ( StringUtils.isBlank( groupId ) || StringUtils.isBlank( artifactId ) )
122 return Collections.emptyList();
124 SearchFields searchField = new SearchFields();
125 searchField.setGroupId( groupId );
126 searchField.setArtifactId( artifactId );
127 searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
128 searchField.setRepositories( getObservableRepos() );
132 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
133 return getArtifacts( searchResults );
135 catch ( RepositorySearchException e )
137 log.error( e.getMessage(), e );
138 throw new ArchivaRestServiceException( e.getMessage(), e );
143 public List<Artifact> searchArtifacts( SearchRequest searchRequest )
144 throws ArchivaRestServiceException
146 if ( searchRequest == null )
148 return Collections.emptyList();
150 SearchFields searchField = getModelMapper().map( searchRequest, SearchFields.class );
151 SearchResultLimits limits = new SearchResultLimits( 0 );
152 limits.setPageSize( searchRequest.getPageSize() );
154 // if no repos set we use ones available for the user
155 if ( searchField.getRepositories() == null || searchField.getRepositories().isEmpty() )
157 searchField.setRepositories( getObservableRepos() );
162 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, limits );
163 return getArtifacts( searchResults );
165 catch ( RepositorySearchException e )
167 log.error( e.getMessage(), e );
168 throw new ArchivaRestServiceException( e.getMessage(), e );
173 public GroupIdList getAllGroupIds( List<String> selectedRepos )
174 throws ArchivaRestServiceException
176 List<String> observableRepos = getObservableRepos();
177 List<String> repos = ListUtils.intersection( observableRepos, selectedRepos );
178 if ( repos == null || repos.isEmpty() )
180 return new GroupIdList( Collections.<String>emptyList() );
184 return new GroupIdList( new ArrayList<>( repositorySearch.getAllGroupIds( getPrincipal(), repos ) ) );
186 catch ( RepositorySearchException e )
188 log.error( e.getMessage(), e );
189 throw new ArchivaRestServiceException( e.getMessage(), e );
194 public List<Dependency> getDependencies( String groupId, String artifactId, String version )
195 throws ArchivaRestServiceException
197 return null; //To change body of implemented methods use File | Settings | File Templates.
200 public List<Artifact> getArtifactByChecksum( String checksum )
201 throws ArchivaRestServiceException
203 return null; //To change body of implemented methods use File | Settings | File Templates.
207 public StringList getObservablesRepoIds()
208 throws ArchivaRestServiceException
210 return new StringList( getObservableRepos() );
214 public Response redirectToArtifactFile( String repositoryId, String groupId, String artifactId, String version,
215 String packaging, String classifier )
216 throws ArchivaRestServiceException
222 if ( StringUtils.isEmpty( groupId ) )
224 return Response.status( new Response.StatusType()
227 public int getStatusCode()
229 return Response.Status.BAD_REQUEST.getStatusCode();
233 public Response.Status.Family getFamily()
235 return Response.Status.BAD_REQUEST.getFamily();
239 public String getReasonPhrase()
241 return "groupId mandatory";
246 if ( StringUtils.isEmpty( artifactId ) )
248 return Response.status( new Response.StatusType()
251 public int getStatusCode()
253 return Response.Status.BAD_REQUEST.getStatusCode();
257 public Response.Status.Family getFamily()
259 return Response.Status.BAD_REQUEST.getFamily();
263 public String getReasonPhrase()
265 return "artifactId mandatory";
270 if ( StringUtils.isEmpty( version ) )
272 return Response.status( new Response.StatusType()
275 public int getStatusCode()
277 return Response.Status.BAD_REQUEST.getStatusCode();
281 public Response.Status.Family getFamily()
283 return Response.Status.BAD_REQUEST.getFamily();
287 public String getReasonPhrase()
289 return "version mandatory";
294 SearchFields searchField = new SearchFields();
295 searchField.setGroupId( groupId );
296 searchField.setArtifactId( artifactId );
297 searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
298 searchField.setVersion( version );
299 searchField.setClassifier( classifier );
300 List<String> userRepos = getObservablesRepoIds().getStrings();
301 searchField.setRepositories(
302 StringUtils.isEmpty( repositoryId ) ? userRepos : Arrays.asList( repositoryId ) );
303 searchField.setExactSearch( true );
304 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
305 List<Artifact> artifacts = getArtifacts( searchResults );
307 if ( artifacts.isEmpty() )
309 return Response.status( new Response.StatusType()
312 public int getStatusCode()
314 return Response.Status.NO_CONTENT.getStatusCode();
318 public Response.Status.Family getFamily()
320 return Response.Status.NO_CONTENT.getFamily();
324 public String getReasonPhrase()
326 return "your query doesn't return any artifact";
331 // TODO improve that with querying lucene with null value for classifier
332 // so simple loop and retain only artifact with null classifier
333 if ( classifier == null )
335 List<Artifact> filteredArtifacts = new ArrayList<>( artifacts.size() );
336 for ( Artifact artifact : artifacts )
338 if ( artifact.getClassifier() == null )
340 filteredArtifacts.add( artifact );
344 artifacts = filteredArtifacts;
347 // TODO return json result of the query ?
348 if ( artifacts.size() > 1 )
350 return Response.status( new Response.StatusType()
353 public int getStatusCode()
355 return Response.Status.BAD_REQUEST.getStatusCode();
359 public Response.Status.Family getFamily()
361 return Response.Status.BAD_REQUEST.getFamily();
365 public String getReasonPhrase()
367 return "your query return more than one artifact";
372 String artifactUrl = null;
374 Artifact artifact = artifacts.get( 0 );
376 // we need to configure correctly the repositoryId
377 if ( StringUtils.isEmpty( repositoryId ) )
379 // is it a good one? if yes nothing to
380 // if not search the repo who is proxy for this remote
381 if ( !userRepos.contains( artifact.getContext() ) )
383 for ( Map.Entry<String, List<ProxyConnector>> entry : proxyConnectorAdmin.getProxyConnectorAsMap().entrySet() )
385 for ( ProxyConnector proxyConnector : entry.getValue() )
387 if ( StringUtils.equals( "remote-" + proxyConnector.getTargetRepoId(),
388 artifact.getContext() ) //
389 && userRepos.contains( entry.getKey() ) )
391 return Response.temporaryRedirect(
392 new URI( getArtifactUrl( artifact, entry.getKey() ) ) ).build();
402 artifactUrl = getArtifactUrl( artifact, repositoryId );
405 return Response.temporaryRedirect( new URI( artifactUrl ) ).build();
407 catch ( Exception e )
409 throw new ArchivaRestServiceException( e.getMessage(), e );
413 //-------------------------------------
415 //-------------------------------------
416 protected List<Artifact> getArtifacts( SearchResults searchResults )
417 throws ArchivaRestServiceException
420 if ( searchResults == null || searchResults.isEmpty() )
422 return Collections.emptyList();
424 List<Artifact> artifacts = new ArrayList<>( searchResults.getReturnedHitsCount() );
425 for ( SearchResultHit hit : searchResults.getHits() )
427 // duplicate Artifact one per available version
428 if ( hit.getVersions().size() > 0 )
430 for ( String version : hit.getVersions() )
433 Artifact versionned = getModelMapper().map( hit, Artifact.class );
435 if ( StringUtils.isNotBlank( version ) )
437 versionned.setVersion( version );
438 versionned.setUrl( getArtifactUrl( versionned ) );
440 artifacts.add( versionned );