1 package org.apache.archiva.rest.services;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.common.utils.VersionComparator;
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.metadata.model.ArtifactMetadata;
31 import org.apache.archiva.metadata.repository.MetadataRepository;
32 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
33 import org.apache.archiva.metadata.repository.RepositorySession;
34 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
35 import org.apache.archiva.rest.api.model.ChecksumSearch;
36 import org.apache.archiva.rest.api.model.GroupIdList;
37 import org.apache.archiva.rest.api.model.SearchRequest;
38 import org.apache.archiva.rest.api.model.StringList;
39 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
40 import org.apache.archiva.rest.api.services.SearchService;
41 import org.apache.commons.collections.ListUtils;
42 import org.apache.commons.lang.StringUtils;
43 import org.springframework.stereotype.Service;
44
45 import javax.inject.Inject;
46 import javax.ws.rs.core.Response;
47 import java.net.URI;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.HashSet;
53 import java.util.List;
54 import java.util.Set;
55 import java.util.TreeMap;
56
57
58
59
60 @Service( "searchService#rest" )
61 public class DefaultSearchService
62 extends AbstractRestService
63 implements SearchService
64 {
65
66 private static final String LATEST_KEYWORD = "LATEST";
67
68 @Inject
69 private RepositorySearch repositorySearch;
70
71 @Inject
72 private RepositorySessionFactory repositorySessionFactory;
73
74 @Override
75 public List<Artifact> quickSearch( String queryString )
76 throws ArchivaRestServiceException
77 {
78 if ( StringUtils.isBlank( queryString ) )
79 {
80 return Collections.emptyList();
81 }
82
83 SearchResultLimits limits = new SearchResultLimits( 0 );
84 try
85 {
86 SearchResults searchResults =
87 repositorySearch.search( getPrincipal(), getObservableRepos(), queryString, limits,
88 Collections.<String>emptyList() );
89 return getArtifacts( searchResults );
90
91 }
92 catch ( RepositorySearchException e )
93 {
94 log.error( e.getMessage(), e );
95 throw new ArchivaRestServiceException( e.getMessage(), e );
96 }
97 }
98
99 @Override
100 public List<Artifact> quickSearchWithRepositories( SearchRequest searchRequest )
101 throws ArchivaRestServiceException
102 {
103 String queryString = searchRequest.getQueryTerms();
104 if ( StringUtils.isBlank( queryString ) )
105 {
106 return Collections.emptyList();
107 }
108 List<String> repositories = searchRequest.getRepositories();
109 if ( repositories == null || repositories.isEmpty() )
110 {
111 repositories = getObservableRepos();
112 }
113 SearchResultLimits limits =
114 new SearchResultLimits( searchRequest.getPageSize(), searchRequest.getSelectedPage() );
115 try
116 {
117 SearchResults searchResults = repositorySearch.search( getPrincipal(), repositories, queryString, limits,
118 Collections.<String>emptyList() );
119 return getArtifacts( searchResults );
120
121 }
122 catch ( RepositorySearchException e )
123 {
124 log.error( e.getMessage(), e );
125 throw new ArchivaRestServiceException( e.getMessage(), e );
126 }
127 }
128
129 @Override
130 public List<Artifact> getArtifactVersions( String groupId, String artifactId, String packaging )
131 throws ArchivaRestServiceException
132 {
133 if ( StringUtils.isBlank( groupId ) || StringUtils.isBlank( artifactId ) )
134 {
135 return Collections.emptyList();
136 }
137 SearchFields searchField = new SearchFields();
138 searchField.setGroupId( groupId );
139 searchField.setArtifactId( artifactId );
140 searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
141 searchField.setRepositories( getObservableRepos() );
142
143 try
144 {
145 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
146 return getArtifacts( searchResults );
147 }
148 catch ( RepositorySearchException e )
149 {
150 log.error( e.getMessage(), e );
151 throw new ArchivaRestServiceException( e.getMessage(), e );
152 }
153 }
154
155 @Override
156 public List<Artifact> searchArtifacts( SearchRequest searchRequest )
157 throws ArchivaRestServiceException
158 {
159 if ( searchRequest == null )
160 {
161 return Collections.emptyList();
162 }
163 SearchFields searchField = getModelMapper().map( searchRequest, SearchFields.class );
164 SearchResultLimits limits = new SearchResultLimits( 0 );
165 limits.setPageSize( searchRequest.getPageSize() );
166
167
168 if ( searchField.getRepositories() == null || searchField.getRepositories().isEmpty() )
169 {
170 searchField.setRepositories( getObservableRepos() );
171 }
172
173 try
174 {
175 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, limits );
176 return getArtifacts( searchResults );
177 }
178 catch ( RepositorySearchException e )
179 {
180 log.error( e.getMessage(), e );
181 throw new ArchivaRestServiceException( e.getMessage(), e );
182 }
183 }
184
185 @Override
186 public GroupIdList getAllGroupIds( List<String> selectedRepos )
187 throws ArchivaRestServiceException
188 {
189 List<String> observableRepos = getObservableRepos();
190 List<String> repos = ListUtils.intersection( observableRepos, selectedRepos );
191 if ( repos == null || repos.isEmpty() )
192 {
193 return new GroupIdList( Collections.<String>emptyList() );
194 }
195 try
196 {
197 return new GroupIdList( new ArrayList<>( repositorySearch.getAllGroupIds( getPrincipal(), repos ) ) );
198 }
199 catch ( RepositorySearchException e )
200 {
201 log.error( e.getMessage(), e );
202 throw new ArchivaRestServiceException( e.getMessage(), e );
203 }
204
205 }
206
207
208 public List<Artifact> getArtifactByChecksum( ChecksumSearch checksumSearch )
209 throws ArchivaRestServiceException
210 {
211
212
213 if ( checksumSearch.getRepositories() == null || checksumSearch.getRepositories().isEmpty() )
214 {
215 checksumSearch.setRepositories( getObservableRepos() );
216 }
217
218 RepositorySession repositorySession = repositorySessionFactory.createSession();
219
220 MetadataRepository metadataRepository = repositorySession.getRepository();
221
222 Set<Artifact> artifactSet = new HashSet<>();
223
224 try
225 {
226 for ( String repoId : checksumSearch.getRepositories() )
227 {
228 Collection<ArtifactMetadata> artifactMetadatas =
229 metadataRepository.getArtifactsByChecksum( repoId, checksumSearch.getChecksum() );
230 artifactSet.addAll( buildArtifacts( artifactMetadatas, repoId ) );
231 }
232
233 return new ArrayList<>( artifactSet );
234
235 }
236 catch ( MetadataRepositoryException e )
237 {
238 log.error( e.getMessage(), e );
239 throw new ArchivaRestServiceException( e.getMessage(), e );
240 }
241 finally
242 {
243 repositorySession.closeQuietly();
244 }
245
246
247 }
248
249 @Override
250 public StringList getObservablesRepoIds()
251 throws ArchivaRestServiceException
252 {
253 return new StringList( getObservableRepos() );
254 }
255
256 @Override
257 public Response redirectToArtifactFile( String repositoryId, String groupId, String artifactId, String version,
258 String packaging, String classifier )
259 throws ArchivaRestServiceException
260 {
261 try
262 {
263
264
265 if ( StringUtils.isEmpty( groupId ) )
266 {
267 return Response.status( new Response.StatusType()
268 {
269 @Override
270 public int getStatusCode()
271 {
272 return Response.Status.BAD_REQUEST.getStatusCode();
273 }
274
275 @Override
276 public Response.Status.Family getFamily()
277 {
278 return Response.Status.BAD_REQUEST.getFamily();
279 }
280
281 @Override
282 public String getReasonPhrase()
283 {
284 return "groupId mandatory";
285 }
286 } ).build();
287 }
288
289 if ( StringUtils.isEmpty( version ) )
290 {
291 return Response.status( new Response.StatusType()
292 {
293 @Override
294 public int getStatusCode()
295 {
296 return Response.Status.BAD_REQUEST.getStatusCode();
297 }
298
299 @Override
300 public Response.Status.Family getFamily()
301 {
302 return Response.Status.BAD_REQUEST.getFamily();
303 }
304
305 @Override
306 public String getReasonPhrase()
307 {
308 return "version mandatory";
309 }
310 } ).build();
311 }
312
313 if ( StringUtils.isEmpty( artifactId ) )
314 {
315 return Response.status( new Response.StatusType()
316 {
317 @Override
318 public int getStatusCode()
319 {
320 return Response.Status.BAD_REQUEST.getStatusCode();
321 }
322
323 @Override
324 public Response.Status.Family getFamily()
325 {
326 return Response.Status.BAD_REQUEST.getFamily();
327 }
328
329 @Override
330 public String getReasonPhrase()
331 {
332 return "artifactId mandatory";
333 }
334 } ).build();
335 }
336
337 SearchFields searchField = new SearchFields();
338 searchField.setGroupId( groupId );
339 searchField.setArtifactId( artifactId );
340 searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
341 if ( !StringUtils.equals( version, LATEST_KEYWORD ) )
342 {
343 searchField.setVersion( version );
344 }
345 searchField.setClassifier( classifier );
346 List<String> userRepos = getObservablesRepoIds().getStrings();
347 searchField.setRepositories(
348 StringUtils.isEmpty( repositoryId ) ? userRepos : Arrays.asList( repositoryId ) );
349 searchField.setExactSearch( true );
350 SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
351 List<Artifact> artifacts = getArtifacts( searchResults );
352
353 if ( artifacts.isEmpty() )
354 {
355 return Response.status( new Response.StatusType()
356 {
357 @Override
358 public int getStatusCode()
359 {
360 return Response.Status.NO_CONTENT.getStatusCode();
361 }
362
363 @Override
364 public Response.Status.Family getFamily()
365 {
366 return Response.Status.NO_CONTENT.getFamily();
367 }
368
369 @Override
370 public String getReasonPhrase()
371 {
372 return "your query doesn't return any artifact";
373 }
374 } ).build();
375 }
376
377
378
379 if ( classifier == null )
380 {
381 List<Artifact> filteredArtifacts = new ArrayList<>( artifacts.size() );
382 for ( Artifact artifact : artifacts )
383 {
384 if ( artifact.getClassifier() == null )
385 {
386 filteredArtifacts.add( artifact );
387 }
388 }
389
390 artifacts = filteredArtifacts;
391 }
392
393
394 if ( artifacts.size() > 1 && !StringUtils.equals( version, LATEST_KEYWORD ) )
395 {
396 return Response.status( new Response.StatusType()
397 {
398 @Override
399 public int getStatusCode()
400 {
401 return Response.Status.BAD_REQUEST.getStatusCode();
402 }
403
404 @Override
405 public Response.Status.Family getFamily()
406 {
407 return Response.Status.BAD_REQUEST.getFamily();
408 }
409
410 @Override
411 public String getReasonPhrase()
412 {
413 return "your query return more than one artifact";
414 }
415 } ).build();
416 }
417
418
419 if ( artifacts.size() > 1 && StringUtils.equals( version, LATEST_KEYWORD ) )
420 {
421 TreeMap<String, Artifact> artifactPerVersion = new TreeMap<>( VersionComparator.getInstance() );
422
423 for ( Artifact artifact : artifacts )
424 {
425 artifactPerVersion.put( artifact.getVersion(), artifact );
426 }
427
428 return Response.temporaryRedirect(
429 new URI( artifactPerVersion.lastEntry().getValue().getUrl() ) ).build();
430
431 }
432
433 Artifact artifact = artifacts.get( 0 );
434
435 return Response.temporaryRedirect( new URI( artifact.getUrl() ) ).build();
436 }
437 catch ( Exception e )
438 {
439 throw new ArchivaRestServiceException( e.getMessage(), e );
440 }
441 }
442
443
444
445
446
447 protected List<Artifact> getArtifacts( SearchResults searchResults )
448 throws ArchivaRestServiceException
449 {
450
451 if ( searchResults == null || searchResults.isEmpty() )
452 {
453 return Collections.emptyList();
454 }
455 List<Artifact> artifacts = new ArrayList<>( searchResults.getReturnedHitsCount() );
456 for ( SearchResultHit hit : searchResults.getHits() )
457 {
458
459 if ( hit.getVersions().size() > 0 )
460 {
461 for ( String version : hit.getVersions() )
462 {
463
464 Artifact versionned = getModelMapper().map( hit, Artifact.class );
465
466 if ( StringUtils.isNotBlank( version ) )
467 {
468 versionned.setVersion( version );
469 versionned.setUrl( getArtifactUrl( versionned ) );
470
471 artifacts.add( versionned );
472
473 }
474 }
475 }
476 }
477 return artifacts;
478 }
479
480
481 }