From 20080174a488ad524cdacedc14048ad042b55648 Mon Sep 17 00:00:00 2001 From: James William Dumay Date: Tue, 16 Dec 2008 02:13:25 +0000 Subject: [PATCH] MRM-1037 - Search Usability * timestamp versions are merged to -SNAPSHOT versions * duplicate artifacts are now merge by use of boolean filters * we now search the correct fields * content search has been removed (more accurate results) * added more tokenizers for groupId, artifactId, version, etc * Artifact Id's are weighted to improve quicksearch results git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@726928 13f79535-47bb-0310-9956-ffa450edef68 --- .../lucene/IndexContentConsumer.java | 6 - .../archiva-base/archiva-indexer/pom.xml | 4 + .../filecontent/FileContentAnalyzer.java | 18 +++ .../filecontent/FileContentConverter.java | 9 +- .../filecontent/FileContentHandlers.java | 13 +- .../indexer/filecontent/FileContentKeys.java | 2 - .../filecontent/FileContentRecord.java | 12 -- .../indexer/lucene/LuceneDocumentMaker.java | 36 +++++ .../lucene/analyzers/ArtifactIdTokenizer.java | 45 ++++++ .../search/DefaultCrossRepositorySearch.java | 18 ++- .../indexer/search/SearchResultHit.java | 28 ++-- .../archiva/indexer/search/SearchResults.java | 18 +-- .../DefaultCrossRepositorySearchTest.java | 145 +++++++----------- .../search/FileContentIndexPopulator.java | 21 ++- .../ant/ant-junit/1.6.5/ant-junit-1.6.5.pom | 6 + .../ant-optional/1.5.1/ant-optional-1.5.1.pom | 6 + .../ant/ant/1.5.1/ant-1.5.1.pom | 6 + .../ant/ant/1.5/ant-1.5.pom | 6 + .../maven/archiva/model/ArchivaArtifact.java | 3 + .../archiva/web/action/SearchAction.java | 41 ++++- .../web/action/ShowArtifactAction.java | 7 +- .../src/main/webapp/WEB-INF/jsp/results.jsp | 29 ++-- .../webapp/WEB-INF/tags/showArtifactLink.tag | 5 +- .../services/SearchServiceImplTest.java | 2 - pom.xml | 5 + 25 files changed, 316 insertions(+), 175 deletions(-) create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/analyzers/ArtifactIdTokenizer.java create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-junit/1.6.5/ant-junit-1.6.5.pom create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-optional/1.5.1/ant-optional-1.5.1.pom create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5.1/ant-1.5.1.pom create mode 100644 archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5/ant-1.5.pom diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java index ea3908772..2c805f64c 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java @@ -159,10 +159,8 @@ public class IndexContentConsumer FileContentRecord record = new FileContentRecord(); try { - File file = new File( repositoryDir, path ); record.setRepositoryId( this.repository.getId() ); record.setFilename( path ); - record.setContents( FileUtils.readFileToString( file, null ) ); // Test for possible artifact reference syntax. try @@ -179,10 +177,6 @@ public class IndexContentConsumer index.modifyRecord( record ); } - catch ( IOException e ) - { - triggerConsumerError( READ_CONTENT, "Unable to read file contents: " + e.getMessage() ); - } catch ( RepositoryIndexException e ) { triggerConsumerError( INDEX_ERROR, "Unable to index file contents: " + e.getMessage() ); diff --git a/archiva-modules/archiva-base/archiva-indexer/pom.xml b/archiva-modules/archiva-base/archiva-indexer/pom.xml index 31f88e679..13b1b2b92 100644 --- a/archiva-modules/archiva-base/archiva-indexer/pom.xml +++ b/archiva-modules/archiva-base/archiva-indexer/pom.xml @@ -40,6 +40,10 @@ org.apache.lucene lucene-core + + org.apache.lucene + lucene-queries + org.codehaus.plexus plexus-spring diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentAnalyzer.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentAnalyzer.java index 855d22591..7921022ce 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentAnalyzer.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentAnalyzer.java @@ -23,8 +23,11 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.maven.archiva.indexer.lucene.analyzers.FilenamesTokenizer; +import org.apache.maven.archiva.indexer.lucene.analyzers.ArtifactIdTokenizer; +import org.apache.maven.archiva.indexer.lucene.analyzers.GroupIdTokenizer; import java.io.Reader; +import org.apache.maven.archiva.indexer.lucene.analyzers.VersionTokenizer; /** * FileContentAnalyzer @@ -42,6 +45,21 @@ public class FileContentAnalyzer extends Analyzer return new FilenamesTokenizer( reader ); } + if ( FileContentKeys.ARTIFACTID.equals( field )) + { + return new ArtifactIdTokenizer(reader); + } + + if ( FileContentKeys.GROUPID.equals( field ) ) + { + return new GroupIdTokenizer(reader); + } + + if ( FileContentKeys.VERSION.equals( field )) + { + return new VersionTokenizer(reader); + } + return STANDARD.tokenStream( field, reader ); } } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentConverter.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentConverter.java index ad191f673..cefc5e9ad 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentConverter.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentConverter.java @@ -37,7 +37,6 @@ import java.text.ParseException; public class FileContentConverter implements LuceneEntryConverter { - public Document convert( LuceneRepositoryContentRecord record ) { if ( !( record instanceof FileContentRecord ) ) @@ -55,16 +54,15 @@ public class FileContentConverter // Artifact Reference doc.addFieldTokenized( ArtifactKeys.GROUPID, filecontent.getArtifact().getGroupId() ); doc.addFieldExact( ArtifactKeys.GROUPID_EXACT, filecontent.getArtifact().getGroupId() ); - doc.addFieldTokenized( ArtifactKeys.ARTIFACTID, filecontent.getArtifact().getArtifactId() ); - doc.addFieldExact( ArtifactKeys.ARTIFACTID_EXACT, filecontent.getArtifact().getArtifactId() ); + doc.addFieldTokenized( ArtifactKeys.ARTIFACTID, filecontent.getArtifact().getArtifactId()); //, 2.0f); + doc.addFieldExact( ArtifactKeys.ARTIFACTID_EXACT, filecontent.getArtifact().getArtifactId(), 2.0f); doc.addFieldTokenized( ArtifactKeys.VERSION, filecontent.getArtifact().getVersion() ); doc.addFieldExact( ArtifactKeys.VERSION_EXACT, filecontent.getArtifact().getVersion() ); doc.addFieldTokenized( ArtifactKeys.TYPE, filecontent.getArtifact().getType() ); doc.addFieldUntokenized( ArtifactKeys.CLASSIFIER, filecontent.getArtifact().getClassifier() ); } - + doc.addFieldTokenized( FileContentKeys.FILENAME, filecontent.getFilename() ); - doc.addFieldTokenized( FileContentKeys.CONTENT, filecontent.getContents() ); return doc.getDocument(); } @@ -91,7 +89,6 @@ public class FileContentConverter // Filecontent Specifics record.setFilename( document.get( FileContentKeys.FILENAME ) ); - record.setContents( document.get( FileContentKeys.CONTENT ) ); return record; } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentHandlers.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentHandlers.java index 70a95c9f4..f3058dda0 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentHandlers.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentHandlers.java @@ -43,8 +43,17 @@ public class FileContentHandlers { analyzer = new FileContentAnalyzer(); converter = new FileContentConverter(); - queryParser = new MultiFieldQueryParser( new String[] { FileContentKeys.FILENAME, FileContentKeys.CONTENT }, - analyzer ); + queryParser = new MultiFieldQueryParser( new String[] { + FileContentKeys.FILENAME, + FileContentKeys.ARTIFACTID, + FileContentKeys.GROUPID, + FileContentKeys.ARTIFACTID_EXACT, + FileContentKeys.GROUPID_EXACT, + FileContentKeys.VERSION, + FileContentKeys.VERSION_EXACT}, + analyzer ); + //We prefer the narrowing approach to search results. + queryParser.setDefaultOperator(MultiFieldQueryParser.Operator.AND); } public String getId() diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentKeys.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentKeys.java index 1b9e6260c..343f359a3 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentKeys.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentKeys.java @@ -32,6 +32,4 @@ public class FileContentKeys public static final String ID = "filecontent"; public static final String FILENAME = "filename"; - - public static final String CONTENT = "content"; } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java index 991f7b0a2..0a1221e1e 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java @@ -39,8 +39,6 @@ public class FileContentRecord */ private ArchivaArtifact artifact; - private String contents; - public String getRepositoryId() { return repositoryId; @@ -51,16 +49,6 @@ public class FileContentRecord this.repositoryId = repositoryId; } - public String getContents() - { - return contents; - } - - public void setContents( String contents ) - { - this.contents = contents; - } - public String getPrimaryKey() { return repositoryId + ":" + filename; diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/LuceneDocumentMaker.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/LuceneDocumentMaker.java index 169058be1..347e0e91a 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/LuceneDocumentMaker.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/LuceneDocumentMaker.java @@ -81,6 +81,18 @@ public class LuceneDocumentMaker return this; } + public LuceneDocumentMaker addFieldTokenized( String key, String value, float boost ) + { + if ( value != null ) + { + Field field = new Field( key, value, Field.Store.YES, Field.Index.TOKENIZED ); + field.setBoost(boost); + document.add( field ); + } + + return this; + } + public LuceneDocumentMaker addFieldTokenized( String key, List list ) { if ( ( list != null ) && ( !list.isEmpty() ) ) @@ -101,6 +113,18 @@ public class LuceneDocumentMaker return this; } + public LuceneDocumentMaker addFieldUntokenized( String name, String value, float boost ) + { + if ( value != null ) + { + Field field = new Field( name, value, Field.Store.YES, Field.Index.UN_TOKENIZED ); + field.setBoost(boost); + document.add( field ); + } + + return this; + } + public LuceneDocumentMaker addFieldExact( String name, String value ) { if ( value != null ) @@ -111,6 +135,18 @@ public class LuceneDocumentMaker return this; } + public LuceneDocumentMaker addFieldExact( String name, String value, float boost ) + { + if ( value != null ) + { + Field field = new Field( name, value, Field.Store.NO, Field.Index.UN_TOKENIZED ); + field.setBoost(boost); + document.add( field ); + } + + return this; + } + public Document getDocument() { return this.document; diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/analyzers/ArtifactIdTokenizer.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/analyzers/ArtifactIdTokenizer.java new file mode 100644 index 000000000..2e99c2663 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/lucene/analyzers/ArtifactIdTokenizer.java @@ -0,0 +1,45 @@ +package org.apache.maven.archiva.indexer.lucene.analyzers; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.Reader; +import org.apache.lucene.analysis.CharTokenizer; + +/** + * Lucene Tokenizer for {@link ArtifactKeys#ARTIFACTID} fields. + */ +public class ArtifactIdTokenizer extends CharTokenizer +{ + public ArtifactIdTokenizer( Reader reader ) + { + super( reader ); + } + + /** + * Break on "-" for "atlassian-plugins-core" + * @param c + * @return + */ + @Override + protected boolean isTokenChar(char c) + { + return (c != '-'); + } +} diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java index 624e4bc50..21deef954 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java @@ -28,8 +28,11 @@ import org.apache.lucene.queryParser.MultiFieldQueryParser; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanFilter; import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.DuplicateFilter; import org.apache.lucene.search.Filter; +import org.apache.lucene.search.FilterClause; import org.apache.lucene.search.Hits; import org.apache.lucene.search.MultiSearcher; import org.apache.lucene.search.Query; @@ -46,6 +49,7 @@ import org.apache.maven.archiva.indexer.RepositoryIndexSearchException; import org.apache.maven.archiva.indexer.bytecode.BytecodeHandlers; import org.apache.maven.archiva.indexer.bytecode.BytecodeKeys; import org.apache.maven.archiva.indexer.filecontent.FileContentHandlers; +import org.apache.maven.archiva.indexer.filecontent.FileContentKeys; import org.apache.maven.archiva.indexer.hashcodes.HashcodesHandlers; import org.apache.maven.archiva.indexer.hashcodes.HashcodesKeys; import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter; @@ -208,10 +212,17 @@ public class DefaultCrossRepositorySearch QueryParser parser = new FileContentHandlers().getQueryParser(); LuceneQuery query = null; SearchResults results = null; + + BooleanFilter duplicateFilter = new BooleanFilter(); + DuplicateFilter artifactIdDuplicateFilter = new DuplicateFilter(FileContentKeys.ARTIFACTID_EXACT); + duplicateFilter.add(new FilterClause(artifactIdDuplicateFilter, BooleanClause.Occur.SHOULD)); + DuplicateFilter groupIdDuplicateFilter = new DuplicateFilter(FileContentKeys.GROUPID_EXACT); + duplicateFilter.add(new FilterClause(groupIdDuplicateFilter, BooleanClause.Occur.SHOULD)); + if ( previousSearchTerms == null || previousSearchTerms.isEmpty() ) { query = new LuceneQuery( parser.parse( term ) ); - results = searchAll( query, limits, indexes, null ); + results = searchAll( query, limits, indexes, duplicateFilter ); } else { @@ -224,7 +235,8 @@ public class DefaultCrossRepositorySearch query = new LuceneQuery( booleanQuery ); Filter filter = new QueryWrapperFilter( parser.parse( term ) ); - results = searchAll( query, limits, indexes, filter ); + duplicateFilter.add(new FilterClause(filter, BooleanClause.Occur.SHOULD)); + results = searchAll( query, limits, indexes, duplicateFilter ); } results.getRepositories().addAll( this.localIndexedRepositories ); @@ -268,7 +280,7 @@ public class DefaultCrossRepositorySearch { // Create a multi-searcher for looking up the information. searcher = new MultiSearcher( searchables ); - + // Perform the search. Hits hits = null; if ( filter != null ) diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java index 05c3a1aef..ba3bca500 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java @@ -48,10 +48,9 @@ public class SearchResultHit private String repositoryId = ""; - // Advanced hit, if artifact, all versions of artifact - private List artifacts = new ArrayList(); + private List versions = new ArrayList(); - private List versions = new ArrayList(); + private ArchivaArtifact artifact; public String getContext() { @@ -88,11 +87,10 @@ public class SearchResultHit this.artifactId = artifactId; } - public void addArtifact( ArchivaArtifact artifact ) + public void setArtifact( ArchivaArtifact artifact ) { - this.artifacts.add( artifact ); - - String ver = artifact.getVersion(); + this.artifact = artifact; + final String ver = artifact.getVersion(); if ( !this.versions.contains( ver ) ) { @@ -115,9 +113,9 @@ public class SearchResultHit } } - public List getArtifacts() + public ArchivaArtifact getArtifact() { - return artifacts; + return artifact; } public String getGroupId() @@ -135,11 +133,21 @@ public class SearchResultHit return version; } - public List getVersions() + public void setVersion(String version) + { + this.version = version; + } + + public List getVersions() { return versions; } + public void setVersions(List versions) + { + this.versions = versions; + } + public String getRepositoryId() { return repositoryId; diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java index 50ed79b28..ecb01fbcf 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java @@ -40,7 +40,7 @@ public class SearchResults { private List repositories = new ArrayList(); - private Map hits = new HashMap(); + private Map hits = new HashMap(); private int totalHits; @@ -82,7 +82,7 @@ public class SearchResults } hit.setRepositoryId( bytecode.getRepositoryId() ); - hit.addArtifact( bytecode.getArtifact() ); + hit.setArtifact( bytecode.getArtifact() ); hit.setContext( null ); // TODO: provide context on why this is a valuable hit. this.hits.put( key, hit ); @@ -111,18 +111,16 @@ public class SearchResults hit = new SearchResultHit(); } - hit.addArtifact( hashcodes.getArtifact() ); + hit.setArtifact( hashcodes.getArtifact() ); hit.setContext( null ); // TODO: provide context on why this is a valuable hit. - this.hits.put( key, hit ); + hits.put( key, hit ); } public void addFileContentHit( FileContentRecord filecontent ) { - String key = filecontent.getPrimaryKey(); - - SearchResultHit hit = (SearchResultHit) this.hits.get( key ); - + final String key = filecontent.getPrimaryKey(); + SearchResultHit hit = hits.get( key ); if ( hit == null ) { // Only need to worry about this hit if it is truely new. @@ -135,7 +133,7 @@ public class SearchResults // Test for possible artifact reference ... if( filecontent.getArtifact() != null ) { - hit.addArtifact( filecontent.getArtifact() ); + hit.setArtifact( filecontent.getArtifact() ); } this.hits.put( key, hit ); @@ -147,7 +145,7 @@ public class SearchResults * * @return the list of {@link SearchResultHit} objects. */ - public List getHits() + public List getHits() { return new ArrayList( hits.values() ); } diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java index bfbe2b9af..687712946 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java @@ -126,119 +126,77 @@ public class DefaultCrossRepositorySearchTest return search; } - public void testSearchTerm_Org() - throws Exception - { + public void testSearchArtifactIdHasMoreWieghtThanGroupId() throws Exception + { CrossRepositorySearch search = lookupCrossRepositorySearch(); String expectedRepos[] = new String[] { TEST_DEFAULT_REPO_ID }; - - String expectedResults[] = new String[] { - "org","org2","org3","org4","org5","org6","org7" - }; - - assertSearchResults( expectedRepos, expectedResults, search, "org", null, false ); - } - public void testSearchTerm_Junit() - throws Exception - { - CrossRepositorySearch search = lookupCrossRepositorySearch(); - - String expectedRepos[] = new String[] { - TEST_DEFAULT_REPO_ID - }; - - String expectedResults[] = new String[] { - "junit","junit2","junit3" - }; - - assertSearchResults( expectedRepos, expectedResults, search, "junit", null, false ); + List expectedHits = new ArrayList(); + SearchResultHit hit = new SearchResultHit(); + hit.setGroupId("ant"); + hit.setArtifactId("ant"); + hit.setVersion("1.5"); + expectedHits.add(hit); + + hit = new SearchResultHit(); + hit.setGroupId("ant"); + hit.setArtifactId("ant-optional"); + hit.setVersion("1.5.1"); + expectedHits.add(hit); + + hit = new SearchResultHit(); + hit.setGroupId("ant"); + hit.setArtifactId("ant-junit"); + hit.setVersion("1.6.5"); + expectedHits.add(hit); + + assertSearchResults( expectedRepos, expectedHits, search, "ant", null, false ); } public void testSearchInvalidTerm() throws Exception - { + { CrossRepositorySearch search = lookupCrossRepositorySearch(); String expectedRepos[] = new String[] { TEST_DEFAULT_REPO_ID }; - - String expectedResults[] = new String[] { - // Nothing. - }; - - assertSearchResults( expectedRepos, expectedResults, search, "monosodium", null, false ); - } - - public void testSearchWithinSearchResults() - throws Exception - { - CrossRepositorySearch search = lookupCrossRepositorySearch(); - String expectedRepos[] = new String[] { - TEST_DEFAULT_REPO_ID - }; - - String expectedResults[] = new String[] { - "org","org2","org3","org4","org5","org6","org7" - }; - - // first search - assertSearchResults( expectedRepos, expectedResults, search, "org", null, false ); - - List previousSearchTerms = new ArrayList(); - previousSearchTerms.add( "org" ); - String secondSearchExpectedResults[] = new String[] { - "org.apache.maven.archiva.record", "org.apache.maven.archiva.record2", - "org.apache.maven.archiva.record3", "org.apache.maven.archiva.record4", - "org.apache.maven.archiva.record5", "org.apache.maven.archiva.record6", - "org.apache.maven.archiva.record7" - }; - - //second search - assertSearchResults( expectedRepos, secondSearchExpectedResults, search, "org.apache.maven.archiva.record", - previousSearchTerms, false ); - - previousSearchTerms.add( "org.apache.maven.archiva.record" ); - String thirdSearchExpectedResults[] = new String[] { - "junit", "junit2", "junit3" - }; - - //third search - assertSearchResults( expectedRepos, thirdSearchExpectedResults, search, "junit", previousSearchTerms, false ); + assertSearchResults( expectedRepos, new ArrayList(), search, "monosodium", null, false ); } - + public void testSearchForClassesAndPackages() throws Exception - { + { CrossRepositorySearch search = lookupCrossRepositorySearch(); String expectedRepos[] = new String[] { TEST_DEFAULT_REPO_ID }; - - String expectedResults[] = new String[] { - "archiva-common-1.0.jar" - }; - + + SearchResultHit archivaCommon = new SearchResultHit(); + archivaCommon.setArtifactId("archiva-common"); + archivaCommon.setGroupId("org.apache.maven.archiva"); + archivaCommon.setVersion("1.0"); + // class with packagename search - assertSearchResults( expectedRepos, expectedResults, search, + assertSearchResults( expectedRepos, Arrays.asList(archivaCommon), search, "org.apache.maven.archiva.common.utils.BaseFile", null, true ); // class name search - assertSearchResults( expectedRepos, expectedResults, search, + assertSearchResults( expectedRepos, Arrays.asList(archivaCommon), search, "BaseFile", null, true ); - - String expectedMethodSearchResults[] = new String[] { - "continuum-webapp-1.0.3-SNAPSHOT.war" - }; - + + SearchResultHit hit = new SearchResultHit(); + hit.setGroupId("org.apache.maven.continuum"); + hit.setArtifactId("continuum-webapp"); + hit.setVersion("1.0.3-SNAPSHOT"); + // method search - assertSearchResults( expectedRepos, expectedMethodSearchResults, search, - "org.apache.maven.continuum.web.action.BuildDefinitionAction.isBuildFresh", null, true ); + assertSearchResults( expectedRepos, Arrays.asList(hit), search, + "org.apache.maven.continuum.web.action.BuildDefinitionAction.isBuildFresh", null, true ); } public void testExecuteFilteredSearch() @@ -312,7 +270,7 @@ public class DefaultCrossRepositorySearchTest assertEquals( "Search Result Hits", expectedResults.length, results.getHits().size() ); } - private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, + private void assertSearchResults( String expectedRepos[], List expectedResults, CrossRepositorySearch search, String term, List previousSearchTerms, boolean bytecode ) throws Exception { @@ -325,8 +283,8 @@ public class DefaultCrossRepositorySearchTest SearchResults results = null; if( previousSearchTerms == null ) - { - if( bytecode ) + { + if( bytecode ) { results = search.searchForBytecode( "guest", selectedRepos, term, limits ); } @@ -346,9 +304,16 @@ public class DefaultCrossRepositorySearchTest // TODO: test the repository ids returned. - assertEquals( "Search Result Hits", expectedResults.length, results.getHits().size() ); - // TODO: test the order of hits. - // TODO: test the value of the hits. + assertEquals( "Search Result Hits", expectedResults.size(), results.getHits().size() ); + + for (int i = 0; i < expectedResults.size(); i++) + { + final SearchResultHit expectedResult = expectedResults.get(i); + final SearchResultHit hit = results.getHits().get(i); + assertEquals("artifactid", expectedResult.getArtifactId(), hit.getArtifactId()); + assertEquals("groupid", expectedResult.getGroupId(), hit.getGroupId()); + assertEquals("version", expectedResult.getVersion(), hit.getVersion()); + } } protected ManagedRepositoryConfiguration createRepository( String id, String name, File location ) diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java index c0dc214e8..0bc1b3d64 100644 --- a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java @@ -19,16 +19,18 @@ package org.apache.maven.archiva.indexer.search; * under the License. */ -import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; import org.apache.maven.archiva.model.ArchivaArtifact; import java.io.File; -import java.io.IOException; import java.util.HashMap; import java.util.Map; import junit.framework.AssertionFailedError; +import org.apache.maven.archiva.model.ArtifactReference; +import org.apache.maven.archiva.repository.content.DefaultPathParser; +import org.apache.maven.archiva.repository.content.PathParser; +import org.apache.maven.archiva.repository.layout.LayoutException; /** * FileContentIndexPopulator @@ -62,6 +64,11 @@ public class FileContentIndexPopulator map.put( "test-pom-1.0", createFileContentRecord( repoDir, prefix + "test-pom/1.0/test-pom-1.0.pom" ) ); map.put( "test-skin-1.0", createFileContentRecord( repoDir, prefix + "test-skin/1.0/test-skin-1.0.pom" ) ); + map.put("ant-1.5.pom", createFileContentRecord(repoDir, "ant/ant/1.5/ant-1.5.pom")); + map.put("ant-1.5.1.pom", createFileContentRecord(repoDir, "ant/ant/1.5.1/ant-1.5.1.pom")); + map.put("ant-junit-1.6.5.pom", createFileContentRecord(repoDir, "ant/ant-junit/1.6.5/ant-junit-1.6.5.pom")); + map.put("ant-optional-1.5.1.pom", createFileContentRecord(repoDir, "ant/ant-optional/1.5.1/ant-optional-1.5.1.pom")); + return map; } @@ -78,14 +85,16 @@ public class FileContentIndexPopulator record.setRepositoryId( "test-repo" ); record.setFilename( path ); + PathParser pathParser = new DefaultPathParser(); try { - record.setContents( FileUtils.readFileToString( pathToFile, null ) ); + ArtifactReference reference = pathParser.toArtifactReference(path); + ArchivaArtifact artifact = new ArchivaArtifact( reference ); + record.setArtifact(artifact); } - catch ( IOException e ) + catch (LayoutException e) { - e.printStackTrace(); - throw new AssertionFailedError( "Can't load test file contents: " + pathToFile.getAbsolutePath() ); + throw new RuntimeException(e); } return record; diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-junit/1.6.5/ant-junit-1.6.5.pom b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-junit/1.6.5/ant-junit-1.6.5.pom new file mode 100644 index 000000000..c3710e60b --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-junit/1.6.5/ant-junit-1.6.5.pom @@ -0,0 +1,6 @@ + + 4.0.0 + ant + ant-junit + 1.6.5 + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-optional/1.5.1/ant-optional-1.5.1.pom b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-optional/1.5.1/ant-optional-1.5.1.pom new file mode 100644 index 000000000..9f34b9e3e --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant-optional/1.5.1/ant-optional-1.5.1.pom @@ -0,0 +1,6 @@ + + 4.0.0 + ant + ant-optional + 1.5.1 + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5.1/ant-1.5.1.pom b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5.1/ant-1.5.1.pom new file mode 100644 index 000000000..5ef748993 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5.1/ant-1.5.1.pom @@ -0,0 +1,6 @@ + + 4.0.0 + ant + ant + 1.5.1 + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5/ant-1.5.pom b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5/ant-1.5.pom new file mode 100644 index 000000000..b634f148d --- /dev/null +++ b/archiva-modules/archiva-base/archiva-indexer/src/test/managed-repository/ant/ant/1.5/ant-1.5.pom @@ -0,0 +1,6 @@ + + 4.0.0 + ant + ant + 1.5 + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/ArchivaArtifact.java b/archiva-modules/archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/ArchivaArtifact.java index 54bf1a828..9da58c4ec 100644 --- a/archiva-modules/archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/ArchivaArtifact.java +++ b/archiva-modules/archiva-base/archiva-model/src/main/java/org/apache/maven/archiva/model/ArchivaArtifact.java @@ -131,6 +131,7 @@ public class ArchivaArtifact return StringUtils.isNotEmpty( model.getClassifier() ); } + @Override public int hashCode() { final int PRIME = 31; @@ -146,6 +147,7 @@ public class ArchivaArtifact return result; } + @Override public boolean equals( Object obj ) { if ( this == obj ) @@ -180,6 +182,7 @@ public class ArchivaArtifact return true; } + @Override public String toString() { StringBuffer sb = new StringBuffer(); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java index 939dbc51a..c3d9194fb 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java @@ -46,6 +46,9 @@ import org.apache.maven.archiva.security.UserRepositories; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.Preparable; +import org.apache.maven.archiva.common.utils.VersionUtil; +import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint; +import org.apache.maven.archiva.indexer.search.SearchResultHit; /** * Search all indexed fields by the given criteria. @@ -127,8 +130,6 @@ public class SearchAction private boolean fromResultsPage; - private int num; - public boolean isFromResultsPage() { return fromResultsPage; @@ -231,7 +232,8 @@ public class SearchAction return GlobalResults.ACCESS_TO_NO_REPOS; } - if( SearchUtil.isBytecodeSearch( q ) ) + final boolean isbytecodeSearch = SearchUtil.isBytecodeSearch( q ); + if( isbytecodeSearch ) { results = crossRepoSearch.searchForBytecode( getPrincipal(), selectedRepos, SearchUtil.removeBytecodeKeyword( q ), limits ); } @@ -274,9 +276,41 @@ public class SearchAction buildCompleteQueryString( q ); } + if (!isbytecodeSearch) + { + //Lets get the versions for the artifact we just found and display them + //Yes, this is in the lucene index but its more challenging to get them out when we are searching by project + for (SearchResultHit resultHit : results.getHits()) + { + final List versions = dao.query(new UniqueVersionConstraint(getObservableRepos(), resultHit.getGroupId(), resultHit.getArtifactId())); + if (versions != null && !versions.isEmpty()) + { + resultHit.setVersion(null); + resultHit.setVersions(filterTimestampedSnapshots(versions)); + } + } + } + return SUCCESS; } + /** + * Remove timestamped snapshots from versions + */ + private static List filterTimestampedSnapshots(List versions) + { + final List filtered = new ArrayList(); + for (final String version : versions) + { + final String baseVersion = VersionUtil.getBaseVersion(version); + if (!filtered.contains(baseVersion)) + { + filtered.add(baseVersion); + } + } + return filtered; + } + public String findArtifact() throws Exception { @@ -329,7 +363,6 @@ public class SearchAction catch ( AccessDeniedException e ) { getLogger().warn( e.getMessage(), e ); - // TODO: pass this onto the screen. } catch ( ArchivaSecurityException e ) { diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java index 56fd71aa0..8ec411f0d 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java @@ -108,10 +108,10 @@ public class ShowArtifactAction this.repositoryId = repoBrowsing.getRepositoryId( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); } - catch ( ObjectNotFoundException oe ) + catch ( ObjectNotFoundException e ) { - addActionError( "Unable to find project model for [" + groupId + ":" + artifactId + ":" + version + "]." ); - + getLogger().debug(e.getMessage(), e); + addActionError( e.getMessage() ); return ERROR; } @@ -208,6 +208,7 @@ public class ShowArtifactAction return Collections.emptyList(); } + @Override public void validate() { if ( StringUtils.isBlank( groupId ) ) diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp index 57ba124db..971f00252 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp @@ -20,7 +20,7 @@ <%@ taglib uri="/struts-tags" prefix="s" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> -<%@ taglib prefix="my" tagdir="/WEB-INF/tags" %> +<%@ taglib prefix="archiva" tagdir="/WEB-INF/tags" %> @@ -135,10 +135,10 @@ - + - - + + @@ -151,10 +151,10 @@ - + - - + + @@ -259,12 +259,12 @@

- + +

- +

@@ -292,12 +292,11 @@

- +

- +

diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag index a5327a1a3..3377bf1bb 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag @@ -30,10 +30,7 @@ <%@ attribute name="repositoryId" %> - ${repositoryId} - : - - + diff --git a/archiva-modules/archiva-web/archiva-xmlrpc/archiva-xmlrpc-services/src/test/java/org/apache/archiva/web/xmlrpc/services/SearchServiceImplTest.java b/archiva-modules/archiva-web/archiva-xmlrpc/archiva-xmlrpc-services/src/test/java/org/apache/archiva/web/xmlrpc/services/SearchServiceImplTest.java index 2deb6f1c2..2db1b931c 100644 --- a/archiva-modules/archiva-web/archiva-xmlrpc/archiva-xmlrpc-services/src/test/java/org/apache/archiva/web/xmlrpc/services/SearchServiceImplTest.java +++ b/archiva-modules/archiva-web/archiva-xmlrpc/archiva-xmlrpc-services/src/test/java/org/apache/archiva/web/xmlrpc/services/SearchServiceImplTest.java @@ -152,7 +152,6 @@ public class SearchServiceImplTest FileContentRecord record = new FileContentRecord(); record.setRepositoryId( "repo1.mirror" ); record.setArtifact( artifact ); - record.setContents( "org.apache.archiva:archiva-test:1.0:jar org.apache.archiva.test.MyClassName" ); record.setFilename( "archiva-test-1.0.jar" ); results.addHit( record ); @@ -198,7 +197,6 @@ public class SearchServiceImplTest FileContentRecord record = new FileContentRecord(); record.setRepositoryId( "repo1.mirror" ); record.setArtifact( artifact ); - record.setContents( "org.apache.archiva:archiva-test:1.0:jar" ); record.setFilename( "archiva-test-1.0.jar" ); results.addHit( record ); diff --git a/pom.xml b/pom.xml index dbd03d690..3f1362244 100644 --- a/pom.xml +++ b/pom.xml @@ -518,6 +518,11 @@ lucene-core 2.4.0
+ + org.apache.lucene + lucene-queries + 2.4.0 + javax.mail mail -- 2.39.5