1 package org.apache.maven.archiva.web.action;
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 com.opensymphony.xwork2.Preparable;
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.metadata.model.ArtifactMetadata;
30 import org.apache.archiva.metadata.repository.MetadataRepository;
31 import org.apache.archiva.metadata.repository.RepositorySession;
32 import org.apache.commons.collections.CollectionUtils;
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.maven.archiva.common.utils.VersionUtil;
35 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
36 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
37 import org.apache.struts2.ServletActionContext;
38 import org.springframework.context.annotation.Scope;
39 import org.springframework.stereotype.Controller;
40 import org.springframework.web.context.WebApplicationContext;
41 import org.springframework.web.context.support.WebApplicationContextUtils;
43 import javax.inject.Inject;
44 import java.net.MalformedURLException;
45 import java.util.ArrayList;
46 import java.util.LinkedHashMap;
47 import java.util.List;
51 * Search all indexed fields by the given criteria.
53 * plexus.component role="com.opensymphony.xwork2.Action" role-hint="searchAction" instantiation-strategy="per-lookup"
55 @Controller( "searchAction" )
57 public class SearchAction
58 extends AbstractRepositoryBasedAction
65 // FIXME olamy WTF here??
66 private ArchivaConfiguration archivaConfiguration;
73 private SearchResults results;
75 private static final String RESULTS = "results";
77 private static final String ARTIFACT = "artifact";
79 private List<ArtifactMetadata> databaseResults;
81 private int currentPage = 0;
83 private int totalPages;
85 private boolean searchResultsOnly;
87 private String completeQueryString;
89 private static final String COMPLETE_QUERY_STRING_SEPARATOR = ";";
91 private List<String> managedRepositoryList = new ArrayList<String>();
93 private String groupId;
95 private String artifactId;
97 private String version;
99 private String className;
101 private int rowCount = 30;
103 private String repositoryId;
105 private boolean fromFilterSearch;
107 private boolean filterSearch = false;
109 private boolean fromResultsPage;
112 private RepositorySearch nexusSearch;
114 private Map<String, String> searchFields;
116 private String infoMessage;
118 public boolean isFromResultsPage()
120 return fromResultsPage;
123 public void setFromResultsPage( boolean fromResultsPage )
125 this.fromResultsPage = fromResultsPage;
128 public boolean isFromFilterSearch()
130 return fromFilterSearch;
133 public void setFromFilterSearch( boolean fromFilterSearch )
135 this.fromFilterSearch = fromFilterSearch;
138 public void prepare()
140 managedRepositoryList = getObservableRepos();
142 if ( managedRepositoryList.size() > 0 )
144 managedRepositoryList.add( "all" );
147 searchFields = new LinkedHashMap<String, String>();
148 searchFields.put( "groupId", "Group ID" );
149 searchFields.put( "artifactId", "Artifact ID" );
150 searchFields.put( "version", "Version" );
151 searchFields.put( "className", "Class/Package Name" );
152 searchFields.put( "rowCount", "Row Count" );
154 super.clearErrorsAndMessages();
158 private void clearSearchFields()
169 // advanced search MRM-90 -- filtered search
170 public String filteredSearch()
171 throws MalformedURLException
173 if ( ( groupId == null || "".equals( groupId ) ) && ( artifactId == null || "".equals( artifactId ) )
174 && ( className == null || "".equals( className ) ) && ( version == null || "".equals( version ) ) )
176 addActionError( "Advanced Search - At least one search criteria must be provided." );
180 fromFilterSearch = true;
182 if ( CollectionUtils.isEmpty( managedRepositoryList ) )
184 return GlobalResults.ACCESS_TO_NO_REPOS;
187 SearchResultLimits limits = new SearchResultLimits( currentPage );
188 limits.setPageSize( rowCount );
189 List<String> selectedRepos = new ArrayList<String>();
191 if ( repositoryId == null || StringUtils.isBlank( repositoryId ) || "all".equals(
192 StringUtils.stripToEmpty( repositoryId ) ) )
194 selectedRepos = getObservableRepos();
198 selectedRepos.add( repositoryId );
201 if ( CollectionUtils.isEmpty( selectedRepos ) )
203 return GlobalResults.ACCESS_TO_NO_REPOS;
206 SearchFields searchFields = new SearchFields( groupId, artifactId, version, null, className, selectedRepos );
208 log.debug( "filteredSearch with searchFields {}", searchFields );
210 // TODO: add packaging in the list of fields for advanced search (UI)?
213 results = getNexusSearch().search( getPrincipal(), searchFields, limits );
215 catch ( RepositorySearchException e )
217 addActionError( e.getMessage() );
221 if ( results.isEmpty() )
223 addActionError( "No results found" );
227 totalPages = results.getTotalHits() / limits.getPageSize();
229 if ( ( results.getTotalHits() % limits.getPageSize() ) != 0 )
231 totalPages = totalPages + 1;
234 for ( SearchResultHit hit : results.getHits() )
236 final String version = hit.getVersion();
237 if ( version != null )
239 hit.setVersion( VersionUtil.getBaseVersion( version ) );
246 @SuppressWarnings( "unchecked" )
247 public String quickSearch()
248 throws MalformedURLException
250 /* TODO: give action message if indexing is in progress.
251 * This should be based off a count of 'unprocessed' artifacts.
252 * This (yet to be written) routine could tell the user that X (unprocessed) artifacts are not yet
253 * present in the full text search.
256 assert q != null && q.length() != 0;
258 fromFilterSearch = false;
260 SearchResultLimits limits = new SearchResultLimits( currentPage );
262 List<String> selectedRepos = getObservableRepos();
263 if ( CollectionUtils.isEmpty( selectedRepos ) )
265 return GlobalResults.ACCESS_TO_NO_REPOS;
268 log.debug( "quickSearch with selectedRepos {} query {}", selectedRepos, q );
272 if ( searchResultsOnly && !completeQueryString.equals( "" ) )
275 getNexusSearch().search( getPrincipal(), selectedRepos, q, limits, parseCompleteQueryString() );
279 completeQueryString = "";
280 results = getNexusSearch().search( getPrincipal(), selectedRepos, q, limits, null );
283 catch ( RepositorySearchException e )
285 addActionError( e.getMessage() );
289 if ( results.isEmpty() )
291 addActionError( "No results found" );
295 totalPages = results.getTotalHits() / limits.getPageSize();
297 if ( ( results.getTotalHits() % limits.getPageSize() ) != 0 )
299 totalPages = totalPages + 1;
302 if ( !isEqualToPreviousSearchTerm( q ) )
304 buildCompleteQueryString( q );
310 public String findArtifact()
313 // TODO: give action message if indexing is in progress
315 if ( StringUtils.isBlank( q ) )
317 addActionError( "Unable to search for a blank checksum" );
321 databaseResults = new ArrayList<ArtifactMetadata>();
322 RepositorySession repositorySession = repositorySessionFactory.createSession();
325 MetadataRepository metadataRepository = repositorySession.getRepository();
326 for ( String repoId : getObservableRepos() )
328 databaseResults.addAll( metadataRepository.getArtifactsByChecksum( repoId, q ) );
333 repositorySession.close();
336 if ( databaseResults.isEmpty() )
338 addActionError( "No results found" );
342 if ( databaseResults.size() == 1 )
344 // 1 hit? return it's information directly!
351 public String doInput()
356 private void buildCompleteQueryString( String searchTerm )
358 if ( searchTerm.indexOf( COMPLETE_QUERY_STRING_SEPARATOR ) != -1 )
360 searchTerm = StringUtils.remove( searchTerm, COMPLETE_QUERY_STRING_SEPARATOR );
363 if ( completeQueryString == null || "".equals( completeQueryString ) )
365 completeQueryString = searchTerm;
369 completeQueryString = completeQueryString + COMPLETE_QUERY_STRING_SEPARATOR + searchTerm;
373 private List<String> parseCompleteQueryString()
375 List<String> parsedCompleteQueryString = new ArrayList<String>();
376 String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
377 CollectionUtils.addAll( parsedCompleteQueryString, parsed );
379 return parsedCompleteQueryString;
382 private boolean isEqualToPreviousSearchTerm( String searchTerm )
384 if ( !"".equals( completeQueryString ) )
386 String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
387 if ( StringUtils.equalsIgnoreCase( searchTerm, parsed[parsed.length - 1] ) )
401 public void setQ( String q )
406 public SearchResults getResults()
411 public List<ArtifactMetadata> getDatabaseResults()
413 return databaseResults;
416 public void setCurrentPage( int page )
418 this.currentPage = page;
421 public int getCurrentPage()
426 public int getTotalPages()
431 public void setTotalPages( int totalPages )
433 this.totalPages = totalPages;
436 public boolean isSearchResultsOnly()
438 return searchResultsOnly;
441 public void setSearchResultsOnly( boolean searchResultsOnly )
443 this.searchResultsOnly = searchResultsOnly;
446 public String getCompleteQueryString()
448 return completeQueryString;
451 public void setCompleteQueryString( String completeQueryString )
453 this.completeQueryString = completeQueryString;
456 public ArchivaConfiguration getArchivaConfiguration()
458 return archivaConfiguration;
461 public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
463 this.archivaConfiguration = archivaConfiguration;
466 public Map<String, ManagedRepositoryConfiguration> getManagedRepositories()
468 return getArchivaConfiguration().getConfiguration().getManagedRepositoriesAsMap();
471 public void setManagedRepositories( Map<String, ManagedRepositoryConfiguration> managedRepositories )
475 public String getGroupId()
480 public void setGroupId( String groupId )
482 this.groupId = groupId;
485 public String getArtifactId()
490 public void setArtifactId( String artifactId )
492 this.artifactId = artifactId;
495 public String getVersion()
500 public void setVersion( String version )
502 this.version = version;
505 public int getRowCount()
510 public void setRowCount( int rowCount )
512 this.rowCount = rowCount;
515 public boolean isFilterSearch()
520 public void setFilterSearch( boolean filterSearch )
522 this.filterSearch = filterSearch;
525 public String getRepositoryId()
530 public void setRepositoryId( String repositoryId )
532 this.repositoryId = repositoryId;
535 public List<String> getManagedRepositoryList()
537 return managedRepositoryList;
540 public void setManagedRepositoryList( List<String> managedRepositoryList )
542 this.managedRepositoryList = managedRepositoryList;
545 public String getClassName()
550 public void setClassName( String className )
552 this.className = className;
555 public RepositorySearch getNexusSearch()
557 if ( nexusSearch == null )
559 WebApplicationContext wac =
560 WebApplicationContextUtils.getRequiredWebApplicationContext( ServletActionContext.getServletContext() );
561 nexusSearch = wac.getBean( "nexusSearch", RepositorySearch.class );
566 public void setNexusSearch( RepositorySearch nexusSearch )
568 this.nexusSearch = nexusSearch;
571 public Map<String, String> getSearchFields()
576 public void setSearchFields( Map<String, String> searchFields )
578 this.searchFields = searchFields;
581 public String getInfoMessage()
586 public void setInfoMessage( String infoMessage )
588 this.infoMessage = infoMessage;