]> source.dussan.org Git - archiva.git/blob
c8c46210f136cd755b2ab775b2b908cee3fe97aa
[archiva.git] /
1 package org.apache.archiva.rest.services;
2
3 /*
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
39
40 import javax.inject.Inject;
41 import javax.ws.rs.core.Response;
42 import java.net.URI;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.List;
47 import java.util.Map;
48
49 /**
50  * @author Olivier Lamy
51  */
52 @Service("searchService#rest")
53 public class DefaultSearchService
54     extends AbstractRestService
55     implements SearchService
56 {
57
58     @Inject
59     private RepositorySearch repositorySearch;
60
61     @Override
62     public List<Artifact> quickSearch( String queryString )
63         throws ArchivaRestServiceException
64     {
65         if ( StringUtils.isBlank( queryString ) )
66         {
67             return Collections.emptyList();
68         }
69
70         SearchResultLimits limits = new SearchResultLimits( 0 );
71         try
72         {
73             SearchResults searchResults =
74                 repositorySearch.search( getPrincipal(), getObservableRepos(), queryString, limits,
75                                          Collections.<String>emptyList() );
76             return getArtifacts( searchResults );
77
78         }
79         catch ( RepositorySearchException e )
80         {
81             log.error( e.getMessage(), e );
82             throw new ArchivaRestServiceException( e.getMessage(), e );
83         }
84     }
85
86     @Override
87     public List<Artifact> quickSearchWithRepositories( SearchRequest searchRequest )
88         throws ArchivaRestServiceException
89     {
90         String queryString = searchRequest.getQueryTerms();
91         if ( StringUtils.isBlank( queryString ) )
92         {
93             return Collections.emptyList();
94         }
95         List<String> repositories = searchRequest.getRepositories();
96         if ( repositories == null || repositories.isEmpty() )
97         {
98             repositories = getObservableRepos();
99         }
100         SearchResultLimits limits =
101             new SearchResultLimits( searchRequest.getPageSize(), searchRequest.getSelectedPage() );
102         try
103         {
104             SearchResults searchResults = repositorySearch.search( getPrincipal(), repositories, queryString, limits,
105                                                                    Collections.<String>emptyList() );
106             return getArtifacts( searchResults );
107
108         }
109         catch ( RepositorySearchException e )
110         {
111             log.error( e.getMessage(), e );
112             throw new ArchivaRestServiceException( e.getMessage(), e );
113         }
114     }
115
116     @Override
117     public List<Artifact> getArtifactVersions( String groupId, String artifactId, String packaging )
118         throws ArchivaRestServiceException
119     {
120         if ( StringUtils.isBlank( groupId ) || StringUtils.isBlank( artifactId ) )
121         {
122             return Collections.emptyList();
123         }
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() );
129
130         try
131         {
132             SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, null );
133             return getArtifacts( searchResults );
134         }
135         catch ( RepositorySearchException e )
136         {
137             log.error( e.getMessage(), e );
138             throw new ArchivaRestServiceException( e.getMessage(), e );
139         }
140     }
141
142     @Override
143     public List<Artifact> searchArtifacts( SearchRequest searchRequest )
144         throws ArchivaRestServiceException
145     {
146         if ( searchRequest == null )
147         {
148             return Collections.emptyList();
149         }
150         SearchFields searchField = getModelMapper().map( searchRequest, SearchFields.class );
151         SearchResultLimits limits = new SearchResultLimits( 0 );
152         limits.setPageSize( searchRequest.getPageSize() );
153
154         // if no repos set we use ones available for the user
155         if ( searchField.getRepositories() == null || searchField.getRepositories().isEmpty() )
156         {
157             searchField.setRepositories( getObservableRepos() );
158         }
159
160         try
161         {
162             SearchResults searchResults = repositorySearch.search( getPrincipal(), searchField, limits );
163             return getArtifacts( searchResults );
164         }
165         catch ( RepositorySearchException e )
166         {
167             log.error( e.getMessage(), e );
168             throw new ArchivaRestServiceException( e.getMessage(), e );
169         }
170     }
171
172     @Override
173     public GroupIdList getAllGroupIds( List<String> selectedRepos )
174         throws ArchivaRestServiceException
175     {
176         List<String> observableRepos = getObservableRepos();
177         List<String> repos = ListUtils.intersection( observableRepos, selectedRepos );
178         if ( repos == null || repos.isEmpty() )
179         {
180             return new GroupIdList( Collections.<String>emptyList() );
181         }
182         try
183         {
184             return new GroupIdList( new ArrayList<>( repositorySearch.getAllGroupIds( getPrincipal(), repos ) ) );
185         }
186         catch ( RepositorySearchException e )
187         {
188             log.error( e.getMessage(), e );
189             throw new ArchivaRestServiceException( e.getMessage(), e );
190         }
191
192     }
193
194     public List<Dependency> getDependencies( String groupId, String artifactId, String version )
195         throws ArchivaRestServiceException
196     {
197         return null;  //To change body of implemented methods use File | Settings | File Templates.
198     }
199
200     public List<Artifact> getArtifactByChecksum( String checksum )
201         throws ArchivaRestServiceException
202     {
203         return null;  //To change body of implemented methods use File | Settings | File Templates.
204     }
205
206     @Override
207     public StringList getObservablesRepoIds()
208         throws ArchivaRestServiceException
209     {
210         return new StringList( getObservableRepos() );
211     }
212
213     @Override
214     public Response redirectToArtifactFile( String repositoryId, String groupId, String artifactId, String version,
215                                             String packaging, String classifier )
216         throws ArchivaRestServiceException
217     {
218         try
219         {
220             // validate query
221
222             if ( StringUtils.isEmpty( groupId ) )
223             {
224                 return Response.status( new Response.StatusType()
225                 {
226                     @Override
227                     public int getStatusCode()
228                     {
229                         return Response.Status.BAD_REQUEST.getStatusCode();
230                     }
231
232                     @Override
233                     public Response.Status.Family getFamily()
234                     {
235                         return Response.Status.BAD_REQUEST.getFamily();
236                     }
237
238                     @Override
239                     public String getReasonPhrase()
240                     {
241                         return "groupId mandatory";
242                     }
243                 } ).build();
244             }
245
246             if ( StringUtils.isEmpty( artifactId ) )
247             {
248                 return Response.status( new Response.StatusType()
249                 {
250                     @Override
251                     public int getStatusCode()
252                     {
253                         return Response.Status.BAD_REQUEST.getStatusCode();
254                     }
255
256                     @Override
257                     public Response.Status.Family getFamily()
258                     {
259                         return Response.Status.BAD_REQUEST.getFamily();
260                     }
261
262                     @Override
263                     public String getReasonPhrase()
264                     {
265                         return "artifactId mandatory";
266                     }
267                 } ).build();
268             }
269
270             if ( StringUtils.isEmpty( version ) )
271             {
272                 return Response.status( new Response.StatusType()
273                 {
274                     @Override
275                     public int getStatusCode()
276                     {
277                         return Response.Status.BAD_REQUEST.getStatusCode();
278                     }
279
280                     @Override
281                     public Response.Status.Family getFamily()
282                     {
283                         return Response.Status.BAD_REQUEST.getFamily();
284                     }
285
286                     @Override
287                     public String getReasonPhrase()
288                     {
289                         return "version mandatory";
290                     }
291                 } ).build();
292             }
293
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 );
306
307             if ( artifacts.isEmpty() )
308             {
309                 return Response.status( new Response.StatusType()
310                 {
311                     @Override
312                     public int getStatusCode()
313                     {
314                         return Response.Status.NO_CONTENT.getStatusCode();
315                     }
316
317                     @Override
318                     public Response.Status.Family getFamily()
319                     {
320                         return Response.Status.NO_CONTENT.getFamily();
321                     }
322
323                     @Override
324                     public String getReasonPhrase()
325                     {
326                         return "your query doesn't return any artifact";
327                     }
328                 } ).build();
329             }
330
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 )
334             {
335                 List<Artifact> filteredArtifacts = new ArrayList<>( artifacts.size() );
336                 for ( Artifact artifact : artifacts )
337                 {
338                     if ( artifact.getClassifier() == null )
339                     {
340                         filteredArtifacts.add( artifact );
341                     }
342                 }
343
344                 artifacts = filteredArtifacts;
345             }
346
347             // TODO return json result of the query ?
348             if ( artifacts.size() > 1 )
349             {
350                 return Response.status( new Response.StatusType()
351                 {
352                     @Override
353                     public int getStatusCode()
354                     {
355                         return Response.Status.BAD_REQUEST.getStatusCode();
356                     }
357
358                     @Override
359                     public Response.Status.Family getFamily()
360                     {
361                         return Response.Status.BAD_REQUEST.getFamily();
362                     }
363
364                     @Override
365                     public String getReasonPhrase()
366                     {
367                         return "your query return more than one artifact";
368                     }
369                 } ).build();
370             }
371
372             String artifactUrl = null;
373
374             Artifact artifact = artifacts.get( 0 );
375
376             // we need to configure correctly the repositoryId
377             if ( StringUtils.isEmpty( repositoryId ) )
378             {
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() ) )
382                 {
383                     for ( Map.Entry<String, List<ProxyConnector>> entry : proxyConnectorAdmin.getProxyConnectorAsMap().entrySet() )
384                     {
385                         for ( ProxyConnector proxyConnector : entry.getValue() )
386                         {
387                             if ( StringUtils.equals( "remote-" + proxyConnector.getTargetRepoId(),
388                                                      artifact.getContext() ) //
389                                 && userRepos.contains( entry.getKey() ) )
390                             {
391                                 return Response.temporaryRedirect(
392                                     new URI( getArtifactUrl( artifact, entry.getKey() ) ) ).build();
393                             }
394                         }
395                     }
396
397                 }
398
399             }
400             else
401             {
402                 artifactUrl = getArtifactUrl( artifact, repositoryId );
403             }
404
405             return Response.temporaryRedirect( new URI( artifactUrl ) ).build();
406         }
407         catch ( Exception e )
408         {
409             throw new ArchivaRestServiceException( e.getMessage(), e );
410         }
411     }
412
413     //-------------------------------------
414     // internal
415     //-------------------------------------
416     protected List<Artifact> getArtifacts( SearchResults searchResults )
417         throws ArchivaRestServiceException
418     {
419
420         if ( searchResults == null || searchResults.isEmpty() )
421         {
422             return Collections.emptyList();
423         }
424         List<Artifact> artifacts = new ArrayList<>( searchResults.getReturnedHitsCount() );
425         for ( SearchResultHit hit : searchResults.getHits() )
426         {
427             // duplicate Artifact one per available version
428             if ( hit.getVersions().size() > 0 )
429             {
430                 for ( String version : hit.getVersions() )
431                 {
432
433                     Artifact versionned = getModelMapper().map( hit, Artifact.class );
434
435                     if ( StringUtils.isNotBlank( version ) )
436                     {
437                         versionned.setVersion( version );
438                         versionned.setUrl( getArtifactUrl( versionned ) );
439
440                         artifacts.add( versionned );
441
442                     }
443                 }
444             }
445         }
446         return artifacts;
447     }
448
449
450 }