mirror of https://github.com/apache/archiva.git
[MRM-330]: Searching gives an HTTP 500
Next phase of work towards a search/find fix. Many improvements in indexer / configuration git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@541680 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cb92f4907f
commit
0c61521dde
|
@ -0,0 +1,53 @@
|
||||||
|
package org.apache.maven.archiva.configuration.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Predicate;
|
||||||
|
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predicate for Repositories with their Indexed setting set to true.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class IndexedRepositoryPredicate
|
||||||
|
implements Predicate
|
||||||
|
{
|
||||||
|
private static IndexedRepositoryPredicate INSTANCE = new IndexedRepositoryPredicate();
|
||||||
|
|
||||||
|
public static IndexedRepositoryPredicate getInstance()
|
||||||
|
{
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean evaluate( Object object )
|
||||||
|
{
|
||||||
|
boolean satisfies = false;
|
||||||
|
|
||||||
|
if ( object instanceof RepositoryConfiguration )
|
||||||
|
{
|
||||||
|
RepositoryConfiguration repoconfig = (RepositoryConfiguration) object;
|
||||||
|
return repoconfig.isIndexed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return satisfies;
|
||||||
|
}
|
||||||
|
}
|
|
@ -135,7 +135,7 @@ public class IndexContentConsumer
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File file = new File( repositoryDir, path );
|
File file = new File( repositoryDir, path );
|
||||||
record.setFile( file );
|
record.setFilename( path );
|
||||||
record.setContents( FileUtils.readFileToString( file, null ) );
|
record.setContents( FileUtils.readFileToString( file, null ) );
|
||||||
|
|
||||||
index.modifyRecord( record );
|
index.modifyRecord( record );
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
package org.apache.maven.archiva.indexer;
|
package org.apache.maven.archiva.indexer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArtifactKeys
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
public class ArtifactKeys
|
public class ArtifactKeys
|
||||||
{
|
{
|
||||||
public static final String GROUPID = "groupId";
|
public static final String GROUPID = "groupId";
|
||||||
|
|
|
@ -19,13 +19,15 @@ package org.apache.maven.archiva.indexer;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.queryParser.QueryParser;
|
import org.apache.lucene.queryParser.QueryParser;
|
||||||
|
import org.apache.lucene.search.Searchable;
|
||||||
|
import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
||||||
import org.apache.maven.archiva.indexer.query.Query;
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common access methods for a Repository Content index.
|
* Common access methods for a Repository Content index.
|
||||||
|
@ -61,17 +63,6 @@ public interface RepositoryContentIndex
|
||||||
public void modifyRecord( LuceneRepositoryContentRecord record )
|
public void modifyRecord( LuceneRepositoryContentRecord record )
|
||||||
throws RepositoryIndexException;
|
throws RepositoryIndexException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Search the index based on the search criteria specified. Returns a list of index records.
|
|
||||||
*
|
|
||||||
* @param query The query that contains the search criteria
|
|
||||||
* @return the index records found
|
|
||||||
* @throws RepositoryIndexSearchException if there is a problem searching
|
|
||||||
* @todo should it return "SearchResult" instances that contain the index record and other search data (like score?)
|
|
||||||
*/
|
|
||||||
List search( Query query )
|
|
||||||
throws RepositoryIndexSearchException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the index already exists.
|
* Check if the index already exists.
|
||||||
*
|
*
|
||||||
|
@ -90,15 +81,6 @@ public interface RepositoryContentIndex
|
||||||
void deleteRecords( Collection records )
|
void deleteRecords( Collection records )
|
||||||
throws RepositoryIndexException;
|
throws RepositoryIndexException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve all records in the index.
|
|
||||||
*
|
|
||||||
* @return the collection of {@link LuceneRepositoryContentRecord} objects.
|
|
||||||
* @throws RepositoryIndexSearchException if there was an error searching the index
|
|
||||||
*/
|
|
||||||
Collection getAllRecords()
|
|
||||||
throws RepositoryIndexSearchException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all primary keys of records in the index.
|
* Retrieve all primary keys of records in the index.
|
||||||
*
|
*
|
||||||
|
@ -128,4 +110,34 @@ public interface RepositoryContentIndex
|
||||||
* @return the id of index.
|
* @return the id of index.
|
||||||
*/
|
*/
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the repository that this index belongs to.
|
||||||
|
*
|
||||||
|
* @return the repository that this index belongs to.
|
||||||
|
*/
|
||||||
|
ArchivaRepository getRepository();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the analyzer in use for this index.
|
||||||
|
*
|
||||||
|
* @return the analyzer in use.
|
||||||
|
*/
|
||||||
|
Analyzer getAnalyzer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the document to record (and back again) converter.
|
||||||
|
*
|
||||||
|
* @return the converter in use.
|
||||||
|
*/
|
||||||
|
LuceneEntryConverter getEntryConverter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Searchable for this index.
|
||||||
|
*
|
||||||
|
* @return the Searchable.
|
||||||
|
* @throws RepositoryIndexSearchException if there was a problem creating the searchable.
|
||||||
|
*/
|
||||||
|
Searchable getSearchable()
|
||||||
|
throws RepositoryIndexSearchException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ public class BytecodeEntryConverter implements LuceneEntryConverter
|
||||||
{
|
{
|
||||||
BytecodeRecord record = new BytecodeRecord();
|
BytecodeRecord record = new BytecodeRecord();
|
||||||
|
|
||||||
|
record.setRepositoryId( document.get( LuceneDocumentMaker.REPOSITORY_ID ) );
|
||||||
|
|
||||||
// Artifact Reference
|
// Artifact Reference
|
||||||
String groupId = document.get( ArtifactKeys.GROUPID );
|
String groupId = document.get( ArtifactKeys.GROUPID );
|
||||||
String artifactId = document.get( ArtifactKeys.ARTIFACTID );
|
String artifactId = document.get( ArtifactKeys.ARTIFACTID );
|
||||||
|
|
|
@ -30,8 +30,11 @@ import java.util.List;
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class BytecodeRecord implements LuceneRepositoryContentRecord
|
public class BytecodeRecord
|
||||||
|
implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
|
private String repositoryId;
|
||||||
|
|
||||||
private ArchivaArtifact artifact;
|
private ArchivaArtifact artifact;
|
||||||
|
|
||||||
private String filename;
|
private String filename;
|
||||||
|
@ -62,6 +65,11 @@ public class BytecodeRecord implements LuceneRepositoryContentRecord
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRepositoryId()
|
||||||
|
{
|
||||||
|
return repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPrimaryKey()
|
public String getPrimaryKey()
|
||||||
{
|
{
|
||||||
StringBuffer id = new StringBuffer();
|
StringBuffer id = new StringBuffer();
|
||||||
|
@ -99,6 +107,11 @@ public class BytecodeRecord implements LuceneRepositoryContentRecord
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRepositoryId( String repositoryId )
|
||||||
|
{
|
||||||
|
this.repositoryId = repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
final int PRIME = 31;
|
final int PRIME = 31;
|
||||||
|
@ -161,4 +174,5 @@ public class BytecodeRecord implements LuceneRepositoryContentRecord
|
||||||
sb.append( "]" );
|
sb.append( "]" );
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.apache.maven.archiva.indexer.lucene.LuceneDocumentMaker;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter;
|
import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +32,8 @@ import java.text.ParseException;
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class FileContentConverter implements LuceneEntryConverter
|
public class FileContentConverter
|
||||||
|
implements LuceneEntryConverter
|
||||||
{
|
{
|
||||||
|
|
||||||
public Document convert( LuceneRepositoryContentRecord record )
|
public Document convert( LuceneRepositoryContentRecord record )
|
||||||
|
@ -41,24 +41,26 @@ public class FileContentConverter implements LuceneEntryConverter
|
||||||
if ( !( record instanceof FileContentRecord ) )
|
if ( !( record instanceof FileContentRecord ) )
|
||||||
{
|
{
|
||||||
throw new ClassCastException( "Unable to convert type " + record.getClass().getName() + " to "
|
throw new ClassCastException( "Unable to convert type " + record.getClass().getName() + " to "
|
||||||
+ FileContentRecord.class.getName() + "." );
|
+ FileContentRecord.class.getName() + "." );
|
||||||
}
|
}
|
||||||
|
|
||||||
FileContentRecord filecontent = (FileContentRecord) record;
|
FileContentRecord filecontent = (FileContentRecord) record;
|
||||||
|
|
||||||
LuceneDocumentMaker doc = new LuceneDocumentMaker( filecontent );
|
LuceneDocumentMaker doc = new LuceneDocumentMaker( filecontent );
|
||||||
|
|
||||||
doc.addFieldTokenized( FileContentKeys.FILENAME, filecontent.getFile().getAbsolutePath() );
|
doc.addFieldTokenized( FileContentKeys.FILENAME, filecontent.getFilename() );
|
||||||
doc.addFieldTokenized( FileContentKeys.CONTENT, filecontent.getContents() );
|
doc.addFieldTokenized( FileContentKeys.CONTENT, filecontent.getContents() );
|
||||||
|
|
||||||
return doc.getDocument();
|
return doc.getDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuceneRepositoryContentRecord convert( Document document ) throws ParseException
|
public LuceneRepositoryContentRecord convert( Document document )
|
||||||
|
throws ParseException
|
||||||
{
|
{
|
||||||
FileContentRecord record = new FileContentRecord();
|
FileContentRecord record = new FileContentRecord();
|
||||||
|
|
||||||
record.setFile( new File( document.get( FileContentKeys.FILENAME ) ) );
|
record.setRepositoryId( document.get( LuceneDocumentMaker.REPOSITORY_ID ) );
|
||||||
|
record.setFilename( document.get( FileContentKeys.FILENAME ) );
|
||||||
record.setContents( document.get( FileContentKeys.CONTENT ) );
|
record.setContents( document.get( FileContentKeys.CONTENT ) );
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
|
|
|
@ -29,12 +29,25 @@ import java.io.File;
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class FileContentRecord implements LuceneRepositoryContentRecord
|
public class FileContentRecord
|
||||||
|
implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
private File file;
|
private String repositoryId;
|
||||||
|
|
||||||
|
private String filename;
|
||||||
|
|
||||||
private String contents;
|
private String contents;
|
||||||
|
|
||||||
|
public String getRepositoryId()
|
||||||
|
{
|
||||||
|
return repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositoryId( String repositoryId )
|
||||||
|
{
|
||||||
|
this.repositoryId = repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getContents()
|
public String getContents()
|
||||||
{
|
{
|
||||||
return contents;
|
return contents;
|
||||||
|
@ -45,26 +58,16 @@ public class FileContentRecord implements LuceneRepositoryContentRecord
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getFile()
|
|
||||||
{
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFile( File file )
|
|
||||||
{
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPrimaryKey()
|
public String getPrimaryKey()
|
||||||
{
|
{
|
||||||
return file.getAbsolutePath();
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
final int PRIME = 31;
|
final int PRIME = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = PRIME * result + ( ( file == null ) ? 0 : file.hashCode() );
|
result = PRIME * result + ( ( filename == null ) ? 0 : filename.hashCode() );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,31 +77,40 @@ public class FileContentRecord implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( obj == null )
|
if ( obj == null )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getClass() != obj.getClass() )
|
if ( getClass() != obj.getClass() )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileContentRecord other = (FileContentRecord) obj;
|
final FileContentRecord other = (FileContentRecord) obj;
|
||||||
|
|
||||||
if ( file == null )
|
if ( filename == null )
|
||||||
{
|
{
|
||||||
if ( other.file != null )
|
if ( other.filename != null )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !file.equals( other.file ) )
|
else if ( !filename.equals( other.filename ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFilename()
|
||||||
|
{
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilename( String filename )
|
||||||
|
{
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BytecodeIndexTransformer
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @plexus.component role="org.apache.commons.collections.Transformer" role-hint="bytecode"
|
||||||
|
*/
|
||||||
|
public class BytecodeIndexTransformer
|
||||||
|
implements Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="lucene"
|
||||||
|
*/
|
||||||
|
private RepositoryContentIndexFactory indexFactory;
|
||||||
|
|
||||||
|
public Object transform( Object input )
|
||||||
|
{
|
||||||
|
if ( input instanceof ArchivaRepository )
|
||||||
|
{
|
||||||
|
return indexFactory.createBytecodeIndex( (ArchivaRepository) input );
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FileContentIndexTransformer
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @plexus.component role="org.apache.commons.collections.Transformer" role-hint="filecontent"
|
||||||
|
*/
|
||||||
|
public class FileContentIndexTransformer
|
||||||
|
implements Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="lucene"
|
||||||
|
*/
|
||||||
|
private RepositoryContentIndexFactory indexFactory;
|
||||||
|
|
||||||
|
public Object transform( Object input )
|
||||||
|
{
|
||||||
|
if ( input instanceof ArchivaRepository )
|
||||||
|
{
|
||||||
|
return indexFactory.createFileContentIndex( (ArchivaRepository) input );
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashcodesIndexTransformer
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @plexus.component role="org.apache.commons.collections.Transformer" role-hint="hashcodes"
|
||||||
|
*/
|
||||||
|
public class HashcodesIndexTransformer
|
||||||
|
implements Transformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="lucene"
|
||||||
|
*/
|
||||||
|
private RepositoryContentIndexFactory indexFactory;
|
||||||
|
|
||||||
|
public Object transform( Object input )
|
||||||
|
{
|
||||||
|
if ( input instanceof ArchivaRepository )
|
||||||
|
{
|
||||||
|
return indexFactory.createHashcodeIndex( (ArchivaRepository) input );
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Predicate;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryIndexException;
|
||||||
|
import org.codehaus.plexus.logging.AbstractLogEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the {@link RepositoryContentIndex} object for the existance of an index.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @plexus.component
|
||||||
|
* role="org.apache.commons.collections.Predicate"
|
||||||
|
* role-hint="index-exists"
|
||||||
|
*/
|
||||||
|
public class IndexExistsPredicate
|
||||||
|
extends AbstractLogEnabled
|
||||||
|
implements Predicate
|
||||||
|
{
|
||||||
|
public boolean evaluate( Object object )
|
||||||
|
{
|
||||||
|
boolean satisfies = false;
|
||||||
|
|
||||||
|
if ( object instanceof RepositoryContentIndex )
|
||||||
|
{
|
||||||
|
RepositoryContentIndex index = (RepositoryContentIndex) object;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
satisfies = index.exists();
|
||||||
|
}
|
||||||
|
catch ( RepositoryIndexException e )
|
||||||
|
{
|
||||||
|
getLogger().info(
|
||||||
|
"Repository Content Index [" + index.getId() + "] for repository ["
|
||||||
|
+ index.getRepository().getId() + "] does not exist yet in ["
|
||||||
|
+ index.getIndexDirectory().getAbsolutePath() + "]." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return satisfies;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
||||||
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentIndex;
|
||||||
|
import org.codehaus.plexus.logging.AbstractLogEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchableTransformer
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @plexus.component role="org.apache.commons.collections.Transformer" role-hint="searchable"
|
||||||
|
*/
|
||||||
|
public class SearchableTransformer
|
||||||
|
extends AbstractLogEnabled
|
||||||
|
implements Transformer
|
||||||
|
{
|
||||||
|
public Object transform( Object input )
|
||||||
|
{
|
||||||
|
if ( input instanceof LuceneRepositoryContentIndex )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LuceneRepositoryContentIndex index = (LuceneRepositoryContentIndex) input;
|
||||||
|
return index.getSearchable();
|
||||||
|
}
|
||||||
|
catch ( RepositoryIndexSearchException e )
|
||||||
|
{
|
||||||
|
getLogger().warn("Unable to get searchable for index:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.apache.maven.archiva.indexer.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Predicate;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserAllowedToSearchRepositoryPredicate
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class UserAllowedToSearchRepositoryPredicate
|
||||||
|
implements Predicate
|
||||||
|
{
|
||||||
|
public boolean evaluate( Object object )
|
||||||
|
{
|
||||||
|
boolean satisfies = false;
|
||||||
|
|
||||||
|
if ( object instanceof ArchivaRepository )
|
||||||
|
{
|
||||||
|
// TODO: perform check here.
|
||||||
|
satisfies = true; // Everyone is allowed! (for now)
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println( "AllowedToSearchRepo: " + satisfies );
|
||||||
|
|
||||||
|
return satisfies;
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ public class HashcodesEntryConverter implements LuceneEntryConverter
|
||||||
HashcodesRecord hashcodes = (HashcodesRecord) record;
|
HashcodesRecord hashcodes = (HashcodesRecord) record;
|
||||||
|
|
||||||
LuceneDocumentMaker doc = new LuceneDocumentMaker( hashcodes );
|
LuceneDocumentMaker doc = new LuceneDocumentMaker( hashcodes );
|
||||||
|
|
||||||
// Artifact Reference
|
// Artifact Reference
|
||||||
doc.addFieldTokenized( ArtifactKeys.GROUPID, hashcodes.getArtifact().getGroupId() );
|
doc.addFieldTokenized( ArtifactKeys.GROUPID, hashcodes.getArtifact().getGroupId() );
|
||||||
doc.addFieldExact( ArtifactKeys.GROUPID_EXACT, hashcodes.getArtifact().getGroupId() );
|
doc.addFieldExact( ArtifactKeys.GROUPID_EXACT, hashcodes.getArtifact().getGroupId() );
|
||||||
|
@ -69,6 +69,8 @@ public class HashcodesEntryConverter implements LuceneEntryConverter
|
||||||
public LuceneRepositoryContentRecord convert( Document document ) throws ParseException
|
public LuceneRepositoryContentRecord convert( Document document ) throws ParseException
|
||||||
{
|
{
|
||||||
HashcodesRecord record = new HashcodesRecord();
|
HashcodesRecord record = new HashcodesRecord();
|
||||||
|
|
||||||
|
record.setRepositoryId( document.get( LuceneDocumentMaker.REPOSITORY_ID ) );
|
||||||
|
|
||||||
// Artifact Reference
|
// Artifact Reference
|
||||||
String groupId = document.get( ArtifactKeys.GROUPID );
|
String groupId = document.get( ArtifactKeys.GROUPID );
|
||||||
|
|
|
@ -28,8 +28,11 @@ import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class HashcodesRecord implements LuceneRepositoryContentRecord
|
public class HashcodesRecord
|
||||||
|
implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
|
private String repositoryId;
|
||||||
|
|
||||||
private ArchivaArtifact artifact;
|
private ArchivaArtifact artifact;
|
||||||
|
|
||||||
private String filename;
|
private String filename;
|
||||||
|
@ -60,7 +63,7 @@ public class HashcodesRecord implements LuceneRepositoryContentRecord
|
||||||
|
|
||||||
return id.toString();
|
return id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
final int PRIME = 31;
|
final int PRIME = 31;
|
||||||
|
@ -75,19 +78,19 @@ public class HashcodesRecord implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( obj == null )
|
if ( obj == null )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getClass() != obj.getClass() )
|
if ( getClass() != obj.getClass() )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final HashcodesRecord other = (HashcodesRecord) obj;
|
final HashcodesRecord other = (HashcodesRecord) obj;
|
||||||
|
|
||||||
if ( artifact == null )
|
if ( artifact == null )
|
||||||
{
|
{
|
||||||
if ( other.artifact != null )
|
if ( other.artifact != null )
|
||||||
|
@ -103,6 +106,16 @@ public class HashcodesRecord implements LuceneRepositoryContentRecord
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRepositoryId()
|
||||||
|
{
|
||||||
|
return this.repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositoryId( String repositoryId )
|
||||||
|
{
|
||||||
|
this.repositoryId = repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getFilename()
|
public String getFilename()
|
||||||
{
|
{
|
||||||
return filename;
|
return filename;
|
||||||
|
@ -112,7 +125,7 @@ public class HashcodesRecord implements LuceneRepositoryContentRecord
|
||||||
{
|
{
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.util.List;
|
||||||
public class LuceneDocumentMaker
|
public class LuceneDocumentMaker
|
||||||
{
|
{
|
||||||
public static final String PRIMARY_KEY = "pk";
|
public static final String PRIMARY_KEY = "pk";
|
||||||
|
|
||||||
|
public static final String REPOSITORY_ID = "repoId";
|
||||||
|
|
||||||
private Document document;
|
private Document document;
|
||||||
|
|
||||||
|
@ -52,19 +54,22 @@ public class LuceneDocumentMaker
|
||||||
|
|
||||||
String primaryKey = record.getPrimaryKey();
|
String primaryKey = record.getPrimaryKey();
|
||||||
|
|
||||||
if ( primaryKey == null )
|
if ( StringUtils.isBlank( primaryKey ) )
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException( "Not allowed to have a null primary key." );
|
throw new IllegalArgumentException( "Not allowed to have a blank primary key." );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( primaryKey.trim().length() <= 0 )
|
String repositoryId = record.getRepositoryId();
|
||||||
|
|
||||||
|
if ( StringUtils.isBlank( repositoryId ) )
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException( "Not allowed to have an empty primary key." );
|
throw new IllegalArgumentException( "Not allowed to have a blank repository id." );
|
||||||
}
|
}
|
||||||
|
|
||||||
document = new Document();
|
document = new Document();
|
||||||
|
|
||||||
document.add( new Field( PRIMARY_KEY, primaryKey, Field.Store.NO, Field.Index.UN_TOKENIZED ) );
|
document.add( new Field( PRIMARY_KEY, primaryKey, Field.Store.NO, Field.Index.UN_TOKENIZED ) );
|
||||||
|
document.add( new Field( REPOSITORY_ID, repositoryId, Field.Store.YES, Field.Index.UN_TOKENIZED ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuceneDocumentMaker addFieldTokenized( String key, String value )
|
public LuceneDocumentMaker addFieldTokenized( String key, String value )
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class LuceneQuery
|
||||||
this.query = query;
|
this.query = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
org.apache.lucene.search.Query getLuceneQuery()
|
public org.apache.lucene.search.Query getLuceneQuery()
|
||||||
{
|
{
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.maven.archiva.indexer.lucene;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.IndexModifier;
|
import org.apache.lucene.index.IndexModifier;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
@ -26,17 +27,15 @@ import org.apache.lucene.index.IndexWriter;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermEnum;
|
import org.apache.lucene.index.TermEnum;
|
||||||
import org.apache.lucene.queryParser.QueryParser;
|
import org.apache.lucene.queryParser.QueryParser;
|
||||||
import org.apache.lucene.search.Hits;
|
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
import org.apache.lucene.search.Searchable;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexException;
|
import org.apache.maven.archiva.indexer.RepositoryIndexException;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
||||||
import org.apache.maven.archiva.indexer.query.Query;
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -64,9 +63,12 @@ public class LuceneRepositoryContentIndex
|
||||||
* The Lucene Index Handlers
|
* The Lucene Index Handlers
|
||||||
*/
|
*/
|
||||||
private LuceneIndexHandlers indexHandlers;
|
private LuceneIndexHandlers indexHandlers;
|
||||||
|
|
||||||
|
private ArchivaRepository repository;
|
||||||
|
|
||||||
public LuceneRepositoryContentIndex( File indexDir, LuceneIndexHandlers handlers )
|
public LuceneRepositoryContentIndex( ArchivaRepository repository, File indexDir, LuceneIndexHandlers handlers )
|
||||||
{
|
{
|
||||||
|
this.repository = repository;
|
||||||
this.indexLocation = indexDir;
|
this.indexLocation = indexDir;
|
||||||
this.indexHandlers = handlers;
|
this.indexHandlers = handlers;
|
||||||
}
|
}
|
||||||
|
@ -219,12 +221,6 @@ public class LuceneRepositoryContentIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllRecords()
|
|
||||||
throws RepositoryIndexSearchException
|
|
||||||
{
|
|
||||||
return search( new LuceneQuery( new MatchAllDocsQuery() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection getAllRecordKeys()
|
public Collection getAllRecordKeys()
|
||||||
throws RepositoryIndexException
|
throws RepositoryIndexException
|
||||||
{
|
{
|
||||||
|
@ -267,64 +263,20 @@ public class LuceneRepositoryContentIndex
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public List getAllGroupIds() throws RepositoryIndexException
|
public Searchable getSearchable()
|
||||||
// {
|
throws RepositoryIndexSearchException
|
||||||
// return getAllFieldValues( StandardIndexRecordFields.GROUPID_EXACT );
|
{
|
||||||
// }
|
try
|
||||||
//
|
{
|
||||||
// public List getArtifactIds( String groupId ) throws RepositoryIndexSearchException
|
IndexSearcher searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
|
||||||
// {
|
return searcher;
|
||||||
// return searchField( new TermQuery( new Term( StandardIndexRecordFields.GROUPID_EXACT, groupId ) ),
|
}
|
||||||
// StandardIndexRecordFields.ARTIFACTID );
|
catch ( IOException e )
|
||||||
// }
|
{
|
||||||
//
|
throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
|
||||||
// public List getVersions( String groupId, String artifactId ) throws RepositoryIndexSearchException
|
}
|
||||||
// {
|
}
|
||||||
// BooleanQuery query = new BooleanQuery();
|
|
||||||
// query.add( new TermQuery( new Term( StandardIndexRecordFields.GROUPID_EXACT, groupId ) ),
|
|
||||||
// BooleanClause.Occur.MUST );
|
|
||||||
// query.add( new TermQuery( new Term( StandardIndexRecordFields.ARTIFACTID_EXACT, artifactId ) ),
|
|
||||||
// BooleanClause.Occur.MUST );
|
|
||||||
//
|
|
||||||
// return searchField( query, StandardIndexRecordFields.VERSION );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private List searchField( org.apache.lucene.search.Query luceneQuery, String fieldName )
|
|
||||||
// throws RepositoryIndexSearchException
|
|
||||||
// {
|
|
||||||
// Set results = new LinkedHashSet();
|
|
||||||
//
|
|
||||||
// IndexSearcher searcher;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
|
|
||||||
// }
|
|
||||||
// catch ( IOException e )
|
|
||||||
// {
|
|
||||||
// throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// Hits hits = searcher.search( luceneQuery );
|
|
||||||
// for ( int i = 0; i < hits.length(); i++ )
|
|
||||||
// {
|
|
||||||
// Document doc = hits.doc( i );
|
|
||||||
//
|
|
||||||
// results.add( doc.get( fieldName ) );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch ( IOException e )
|
|
||||||
// {
|
|
||||||
// throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
|
|
||||||
// }
|
|
||||||
// finally
|
|
||||||
// {
|
|
||||||
// closeQuietly( searcher );
|
|
||||||
// }
|
|
||||||
// return new ArrayList( results );
|
|
||||||
// }
|
|
||||||
|
|
||||||
public boolean exists()
|
public boolean exists()
|
||||||
throws RepositoryIndexException
|
throws RepositoryIndexException
|
||||||
|
@ -354,70 +306,26 @@ public class LuceneRepositoryContentIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List search( Query query )
|
|
||||||
throws RepositoryIndexSearchException
|
|
||||||
{
|
|
||||||
LuceneQuery lQuery = (LuceneQuery) query;
|
|
||||||
|
|
||||||
org.apache.lucene.search.Query luceneQuery = lQuery.getLuceneQuery();
|
|
||||||
|
|
||||||
IndexSearcher searcher;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
|
|
||||||
}
|
|
||||||
catch ( IOException e )
|
|
||||||
{
|
|
||||||
throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
|
|
||||||
}
|
|
||||||
|
|
||||||
List records = new ArrayList();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Hits hits = searcher.search( luceneQuery );
|
|
||||||
for ( int i = 0; i < hits.length(); i++ )
|
|
||||||
{
|
|
||||||
Document doc = hits.doc( i );
|
|
||||||
|
|
||||||
records.add( indexHandlers.getConverter().convert( doc ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( IOException e )
|
|
||||||
{
|
|
||||||
throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
|
|
||||||
}
|
|
||||||
catch ( ParseException e )
|
|
||||||
{
|
|
||||||
throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
closeQuietly( searcher );
|
|
||||||
}
|
|
||||||
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QueryParser getQueryParser()
|
public QueryParser getQueryParser()
|
||||||
{
|
{
|
||||||
return this.indexHandlers.getQueryParser();
|
return this.indexHandlers.getQueryParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void closeQuietly( IndexSearcher searcher )
|
public static void closeSearchable( Searchable searchable )
|
||||||
{
|
{
|
||||||
try
|
if( searchable != null )
|
||||||
{
|
{
|
||||||
if ( searcher != null )
|
try
|
||||||
{
|
{
|
||||||
searcher.close();
|
searchable.close();
|
||||||
|
}
|
||||||
|
catch ( IOException e )
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( IOException e )
|
|
||||||
{
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void closeQuietly( TermEnum terms )
|
private static void closeQuietly( TermEnum terms )
|
||||||
throws RepositoryIndexException
|
throws RepositoryIndexException
|
||||||
{
|
{
|
||||||
|
@ -490,4 +398,19 @@ public class LuceneRepositoryContentIndex
|
||||||
{
|
{
|
||||||
return this.indexHandlers.getId();
|
return this.indexHandlers.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArchivaRepository getRepository()
|
||||||
|
{
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Analyzer getAnalyzer()
|
||||||
|
{
|
||||||
|
return this.indexHandlers.getAnalyzer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuceneEntryConverter getEntryConverter()
|
||||||
|
{
|
||||||
|
return this.indexHandlers.getConverter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.maven.archiva.indexer.lucene;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
|
@ -38,7 +39,8 @@ import java.io.File;
|
||||||
*
|
*
|
||||||
* @plexus.component role="org.apache.maven.archiva.indexer.RepositoryContentIndexFactory" role-hint="lucene"
|
* @plexus.component role="org.apache.maven.archiva.indexer.RepositoryContentIndexFactory" role-hint="lucene"
|
||||||
*/
|
*/
|
||||||
public class LuceneRepositoryContentIndexFactory implements RepositoryContentIndexFactory
|
public class LuceneRepositoryContentIndexFactory
|
||||||
|
implements RepositoryContentIndexFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @plexus.requirement
|
* @plexus.requirement
|
||||||
|
@ -48,19 +50,19 @@ public class LuceneRepositoryContentIndexFactory implements RepositoryContentInd
|
||||||
public RepositoryContentIndex createBytecodeIndex( ArchivaRepository repository )
|
public RepositoryContentIndex createBytecodeIndex( ArchivaRepository repository )
|
||||||
{
|
{
|
||||||
File indexDir = toIndexDir( repository, "bytecode" );
|
File indexDir = toIndexDir( repository, "bytecode" );
|
||||||
return new LuceneRepositoryContentIndex( indexDir, new BytecodeHandlers() );
|
return new LuceneRepositoryContentIndex( repository, indexDir, new BytecodeHandlers() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryContentIndex createFileContentIndex( ArchivaRepository repository )
|
public RepositoryContentIndex createFileContentIndex( ArchivaRepository repository )
|
||||||
{
|
{
|
||||||
File indexDir = toIndexDir( repository, "filecontent" );
|
File indexDir = toIndexDir( repository, "filecontent" );
|
||||||
return new LuceneRepositoryContentIndex( indexDir, new FileContentHandlers() );
|
return new LuceneRepositoryContentIndex( repository, indexDir, new FileContentHandlers() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryContentIndex createHashcodeIndex( ArchivaRepository repository )
|
public RepositoryContentIndex createHashcodeIndex( ArchivaRepository repository )
|
||||||
{
|
{
|
||||||
File indexDir = toIndexDir( repository, "hashcodes" );
|
File indexDir = toIndexDir( repository, "hashcodes" );
|
||||||
return new LuceneRepositoryContentIndex( indexDir, new HashcodesHandlers() );
|
return new LuceneRepositoryContentIndex( repository, indexDir, new HashcodesHandlers() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,6 +93,15 @@ public class LuceneRepositoryContentIndexFactory implements RepositoryContentInd
|
||||||
{
|
{
|
||||||
// Use configured index dir.
|
// Use configured index dir.
|
||||||
String repoPath = repoConfig.getIndexDir();
|
String repoPath = repoConfig.getIndexDir();
|
||||||
|
if ( StringUtils.isBlank( repoPath ) )
|
||||||
|
{
|
||||||
|
repoPath = repository.getUrl().getPath();
|
||||||
|
if ( !repoPath.endsWith( "/" ) )
|
||||||
|
{
|
||||||
|
repoPath += "/";
|
||||||
|
}
|
||||||
|
repoPath += ".index";
|
||||||
|
}
|
||||||
indexDir = new File( repoPath, "/" + indexId + "/" );
|
indexDir = new File( repoPath, "/" + indexId + "/" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,4 +32,11 @@ public interface LuceneRepositoryContentRecord
|
||||||
* @return the primary key
|
* @return the primary key
|
||||||
*/
|
*/
|
||||||
public String getPrimaryKey();
|
public String getPrimaryKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the repository that this record belongs to.
|
||||||
|
*
|
||||||
|
* @return the repository id for this record.
|
||||||
|
*/
|
||||||
|
public String getRepositoryId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,26 @@
|
||||||
package org.apache.maven.archiva.indexer.search;
|
package org.apache.maven.archiva.indexer.search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search across repositories for specified term.
|
* Search across repositories in lucene indexes.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
|
@ -13,15 +32,26 @@ public interface CrossRepositorySearch
|
||||||
* Search for the specific term across all repositories.
|
* Search for the specific term across all repositories.
|
||||||
*
|
*
|
||||||
* @param term the term to search for.
|
* @param term the term to search for.
|
||||||
|
* @param limits the limits to apply to the search results.
|
||||||
* @return the results.
|
* @return the results.
|
||||||
*/
|
*/
|
||||||
public SearchResults searchForTerm( String term );
|
public SearchResults searchForTerm( String term, SearchResultLimits limits );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for the specific bytecode across all repositories.
|
||||||
|
*
|
||||||
|
* @param term the term to search for.
|
||||||
|
* @param limits the limits to apply to the search results.
|
||||||
|
* @return the results.
|
||||||
|
*/
|
||||||
|
public SearchResults searchForBytecode( String term, SearchResultLimits limits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for the specific MD5 string across all repositories.
|
* Search for the specific checksum string across all repositories.
|
||||||
*
|
*
|
||||||
* @param md5 the md5 string to search for.
|
* @param checksum the checksum string to search for.
|
||||||
|
* @param limits the limits to apply to the search results.
|
||||||
* @return the results.
|
* @return the results.
|
||||||
*/
|
*/
|
||||||
public SearchResults searchForMd5( String md5 );
|
public SearchResults searchForChecksum( String checksum, SearchResultLimits limits );
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,31 @@ package org.apache.maven.archiva.indexer.search;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections.Predicate;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.AndPredicate;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.queryParser.MultiFieldQueryParser;
|
||||||
import org.apache.lucene.queryParser.ParseException;
|
import org.apache.lucene.queryParser.ParseException;
|
||||||
import org.apache.lucene.queryParser.QueryParser;
|
import org.apache.lucene.queryParser.QueryParser;
|
||||||
|
import org.apache.lucene.search.Hits;
|
||||||
|
import org.apache.lucene.search.MultiSearcher;
|
||||||
|
import org.apache.lucene.search.Searchable;
|
||||||
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
import org.apache.maven.archiva.configuration.ConfigurationNames;
|
import org.apache.maven.archiva.configuration.ConfigurationNames;
|
||||||
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
||||||
|
import org.apache.maven.archiva.configuration.functors.IndexedRepositoryPredicate;
|
||||||
|
import org.apache.maven.archiva.configuration.functors.LocalRepositoryPredicate;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
import org.apache.maven.archiva.indexer.bytecode.BytecodeHandlers;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
import org.apache.maven.archiva.indexer.filecontent.FileContentHandlers;
|
||||||
import org.apache.maven.archiva.indexer.bytecode.BytecodeKeys;
|
import org.apache.maven.archiva.indexer.functors.UserAllowedToSearchRepositoryPredicate;
|
||||||
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.hashcodes.HashcodesKeys;
|
||||||
|
import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
|
import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
|
||||||
import org.apache.maven.archiva.model.ArchivaRepository;
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
||||||
import org.apache.maven.archiva.repository.ArchivaConfigurationAdaptor;
|
import org.apache.maven.archiva.repository.ArchivaConfigurationAdaptor;
|
||||||
import org.codehaus.plexus.logging.AbstractLogEnabled;
|
import org.codehaus.plexus.logging.AbstractLogEnabled;
|
||||||
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
|
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
|
||||||
|
@ -39,12 +51,10 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationExce
|
||||||
import org.codehaus.plexus.registry.Registry;
|
import org.codehaus.plexus.registry.Registry;
|
||||||
import org.codehaus.plexus.registry.RegistryListener;
|
import org.codehaus.plexus.registry.RegistryListener;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultCrossRepositorySearch
|
* DefaultCrossRepositorySearch
|
||||||
|
@ -57,121 +67,199 @@ public class DefaultCrossRepositorySearch
|
||||||
extends AbstractLogEnabled
|
extends AbstractLogEnabled
|
||||||
implements CrossRepositorySearch, RegistryListener, Initializable
|
implements CrossRepositorySearch, RegistryListener, Initializable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
private static final int UNKNOWN = 0;
|
* @plexus.requirement role-hint="bytecode"
|
||||||
|
*/
|
||||||
private static final int FILE_CONTENT = 1;
|
private Transformer bytecodeIndexTransformer;
|
||||||
|
|
||||||
private static final int BYTECODE = 2;
|
|
||||||
|
|
||||||
private static final int HASHCODE = 3;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @plexus.requirement role-hint="lucene"
|
* @plexus.requirement role-hint="filecontent"
|
||||||
*/
|
*/
|
||||||
private RepositoryContentIndexFactory indexFactory;
|
private Transformer filecontentIndexTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="hashcodes"
|
||||||
|
*/
|
||||||
|
private Transformer hashcodesIndexTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="searchable"
|
||||||
|
*/
|
||||||
|
private Transformer searchableTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="index-exists"
|
||||||
|
*/
|
||||||
|
private Predicate indexExistsPredicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @plexus.requirement
|
* @plexus.requirement
|
||||||
*/
|
*/
|
||||||
private ArchivaConfiguration configuration;
|
private ArchivaConfiguration configuration;
|
||||||
|
|
||||||
private Map repositoryMap = new HashMap();
|
private List localIndexedRepositories = new ArrayList();
|
||||||
|
|
||||||
public SearchResults searchForMd5( String md5 )
|
public SearchResults searchForChecksum( String checksum, SearchResultLimits limits )
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
List indexes = getHashcodeIndexes();
|
||||||
return null;
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QueryParser parser = new MultiFieldQueryParser( new String[] { HashcodesKeys.MD5, HashcodesKeys.SHA1 },
|
||||||
|
new HashcodesHandlers().getAnalyzer() );
|
||||||
|
LuceneQuery query = new LuceneQuery( parser.parse( checksum ) );
|
||||||
|
SearchResults results = searchAll( query, limits, indexes );
|
||||||
|
results.getRepositories().addAll( this.localIndexedRepositories );
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
catch ( ParseException e )
|
||||||
|
{
|
||||||
|
getLogger().warn( "Unable to parse query [" + checksum + "]: " + e.getMessage(), e );
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty results.
|
||||||
|
return new SearchResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResults searchForTerm( String term )
|
public SearchResults searchForBytecode( String term, SearchResultLimits limits )
|
||||||
{
|
{
|
||||||
List indexes = new ArrayList();
|
List indexes = getHashcodeIndexes();
|
||||||
|
|
||||||
indexes.addAll( getBytecodeIndexes() );
|
try
|
||||||
indexes.addAll( getFileContentIndexes() );
|
{
|
||||||
indexes.addAll( getHashcodeIndexes() );
|
QueryParser parser = new BytecodeHandlers().getQueryParser();
|
||||||
|
LuceneQuery query = new LuceneQuery( parser.parse( term ) );
|
||||||
|
SearchResults results = searchAll( query, limits, indexes );
|
||||||
|
results.getRepositories().addAll( this.localIndexedRepositories );
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
catch ( ParseException e )
|
||||||
|
{
|
||||||
|
getLogger().warn( "Unable to parse query [" + term + "]: " + e.getMessage(), e );
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty results.
|
||||||
|
return new SearchResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchResults searchForTerm( String term, SearchResultLimits limits )
|
||||||
|
{
|
||||||
|
List indexes = getFileContentIndexes();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QueryParser parser = new FileContentHandlers().getQueryParser();
|
||||||
|
LuceneQuery query = new LuceneQuery( parser.parse( term ) );
|
||||||
|
SearchResults results = searchAll( query, limits, indexes );
|
||||||
|
results.getRepositories().addAll( this.localIndexedRepositories );
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
catch ( ParseException e )
|
||||||
|
{
|
||||||
|
getLogger().warn( "Unable to parse query [" + term + "]: " + e.getMessage(), e );
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty results.
|
||||||
|
return new SearchResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List indexes )
|
||||||
|
{
|
||||||
|
org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery();
|
||||||
|
|
||||||
SearchResults results = new SearchResults();
|
SearchResults results = new SearchResults();
|
||||||
|
|
||||||
results.getRepositories().addAll( this.repositoryMap.values() );
|
if ( indexes.isEmpty() )
|
||||||
|
|
||||||
Iterator it = indexes.iterator();
|
|
||||||
while ( it.hasNext() )
|
|
||||||
{
|
{
|
||||||
RepositoryContentIndex index = (RepositoryContentIndex) it.next();
|
// No point going any further.
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
// Setup the converter
|
||||||
|
LuceneEntryConverter converter = null;
|
||||||
|
RepositoryContentIndex index = (RepositoryContentIndex) indexes.get( 0 );
|
||||||
|
converter = index.getEntryConverter();
|
||||||
|
|
||||||
|
// Process indexes into an array of Searchables.
|
||||||
|
List searchableList = new ArrayList( indexes );
|
||||||
|
CollectionUtils.transform( searchableList, searchableTransformer );
|
||||||
|
|
||||||
|
Searchable searchables[] = new Searchable[searchableList.size()];
|
||||||
|
searchableList.toArray( searchables );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create a multi-searcher for looking up the information.
|
||||||
|
MultiSearcher searcher = new MultiSearcher( searchables );
|
||||||
|
|
||||||
|
// Perform the search.
|
||||||
|
Hits hits = searcher.search( specificQuery );
|
||||||
|
|
||||||
|
int hitCount = hits.length();
|
||||||
|
|
||||||
|
// Now process the limits.
|
||||||
|
results.setLimits( limits );
|
||||||
|
results.setTotalHits( hitCount );
|
||||||
|
|
||||||
|
int fetchCount = limits.getPageSize();
|
||||||
|
int offset = ( limits.getSelectedPage() * limits.getPageSize() );
|
||||||
|
|
||||||
|
if ( limits.getSelectedPage() == SearchResultLimits.ALL_PAGES )
|
||||||
{
|
{
|
||||||
QueryParser parser = index.getQueryParser();
|
fetchCount = hitCount;
|
||||||
LuceneQuery query = new LuceneQuery( parser.parse( term ) );
|
offset = 0;
|
||||||
List hits = index.search( query );
|
}
|
||||||
|
|
||||||
switch ( getIndexId( index ) )
|
// Goto offset.
|
||||||
|
if ( offset < hitCount )
|
||||||
|
{
|
||||||
|
// only process if the offset is within the hit count.
|
||||||
|
for ( int i = 0; i <= fetchCount; i++ )
|
||||||
{
|
{
|
||||||
case BYTECODE:
|
// Stop fetching if we are past the total # of available hits.
|
||||||
results.getBytecodeHits().addAll( hits );
|
if ( offset + i >= hitCount )
|
||||||
break;
|
{
|
||||||
case FILE_CONTENT:
|
|
||||||
results.getContentHits().addAll( hits );
|
|
||||||
break;
|
|
||||||
case HASHCODE:
|
|
||||||
results.getHashcodeHits().addAll( hits );
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Document doc = hits.doc( offset + i );
|
||||||
|
LuceneRepositoryContentRecord record = converter.convert( doc );
|
||||||
|
results.addHit( record );
|
||||||
|
}
|
||||||
|
catch ( java.text.ParseException e )
|
||||||
|
{
|
||||||
|
getLogger().warn( "Unable to parse document into record: " + e.getMessage(), e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( ParseException e )
|
}
|
||||||
{
|
catch ( IOException e )
|
||||||
getLogger().warn( "Unable to parse query [" + term + "]: " + e.getMessage(), e );
|
{
|
||||||
}
|
getLogger().error( "Unable to setup multi-search: " + e.getMessage(), e );
|
||||||
catch ( RepositoryIndexSearchException e )
|
|
||||||
{
|
|
||||||
getLogger().warn( "Unable to search index [" + index + "] for term [" + term + "]: " + e.getMessage(),
|
|
||||||
e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getIndexId( RepositoryContentIndex index )
|
private Predicate getAllowedToSearchReposPredicate()
|
||||||
{
|
{
|
||||||
if ( FileContentKeys.ID.equals( index.getId() ) )
|
return new UserAllowedToSearchRepositoryPredicate();
|
||||||
{
|
|
||||||
return FILE_CONTENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( BytecodeKeys.ID.equals( index.getId() ) )
|
|
||||||
{
|
|
||||||
return BYTECODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( HashcodesKeys.ID.equals( index.getId() ) )
|
|
||||||
{
|
|
||||||
return HASHCODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getBytecodeIndexes()
|
public List getBytecodeIndexes()
|
||||||
{
|
{
|
||||||
List ret = new ArrayList();
|
List ret = new ArrayList();
|
||||||
|
|
||||||
synchronized ( this.repositoryMap )
|
synchronized ( this.localIndexedRepositories )
|
||||||
{
|
{
|
||||||
Iterator it = this.repositoryMap.values().iterator();
|
ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) );
|
||||||
while ( it.hasNext() )
|
CollectionUtils.transform( ret, bytecodeIndexTransformer );
|
||||||
{
|
CollectionUtils.filter( ret, indexExistsPredicate );
|
||||||
ArchivaRepository repo = (ArchivaRepository) it.next();
|
|
||||||
|
|
||||||
if ( !isSearchAllowed( repo ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.add( indexFactory.createBytecodeIndex( repo ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -181,20 +269,11 @@ public class DefaultCrossRepositorySearch
|
||||||
{
|
{
|
||||||
List ret = new ArrayList();
|
List ret = new ArrayList();
|
||||||
|
|
||||||
synchronized ( this.repositoryMap )
|
synchronized ( this.localIndexedRepositories )
|
||||||
{
|
{
|
||||||
Iterator it = this.repositoryMap.values().iterator();
|
ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) );
|
||||||
while ( it.hasNext() )
|
CollectionUtils.transform( ret, filecontentIndexTransformer );
|
||||||
{
|
CollectionUtils.filter( ret, indexExistsPredicate );
|
||||||
ArchivaRepository repo = (ArchivaRepository) it.next();
|
|
||||||
|
|
||||||
if ( !isSearchAllowed( repo ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.add( indexFactory.createFileContentIndex( repo ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -204,37 +283,21 @@ public class DefaultCrossRepositorySearch
|
||||||
{
|
{
|
||||||
List ret = new ArrayList();
|
List ret = new ArrayList();
|
||||||
|
|
||||||
synchronized ( this.repositoryMap )
|
synchronized ( this.localIndexedRepositories )
|
||||||
{
|
{
|
||||||
Iterator it = this.repositoryMap.values().iterator();
|
ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) );
|
||||||
while ( it.hasNext() )
|
CollectionUtils.transform( ret, hashcodesIndexTransformer );
|
||||||
{
|
CollectionUtils.filter( ret, indexExistsPredicate );
|
||||||
ArchivaRepository repo = (ArchivaRepository) it.next();
|
|
||||||
|
|
||||||
if ( !isSearchAllowed( repo ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.add( indexFactory.createHashcodeIndex( repo ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSearchAllowed( ArchivaRepository repo )
|
|
||||||
{
|
|
||||||
// TODO: test if user has permissions to search in this repo.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
|
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
|
||||||
{
|
{
|
||||||
if ( ConfigurationNames.isRepositories( propertyName ) )
|
if ( ConfigurationNames.isRepositories( propertyName ) )
|
||||||
{
|
{
|
||||||
initRepositoryMap();
|
initRepositories();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,28 +306,41 @@ public class DefaultCrossRepositorySearch
|
||||||
/* Nothing to do here */
|
/* Nothing to do here */
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRepositoryMap()
|
private void initRepositories()
|
||||||
{
|
{
|
||||||
synchronized ( this.repositoryMap )
|
synchronized ( this.localIndexedRepositories )
|
||||||
{
|
{
|
||||||
this.repositoryMap.clear();
|
this.localIndexedRepositories.clear();
|
||||||
|
|
||||||
Iterator it = configuration.getConfiguration().createRepositoryMap().entrySet().iterator();
|
Predicate localIndexedRepos = AndPredicate.getInstance( LocalRepositoryPredicate.getInstance(),
|
||||||
while ( it.hasNext() )
|
IndexedRepositoryPredicate.getInstance() );
|
||||||
|
|
||||||
|
Collection repos = CollectionUtils.select( configuration.getConfiguration().getRepositories(),
|
||||||
|
localIndexedRepos );
|
||||||
|
|
||||||
|
Transformer toArchivaRepository = new Transformer()
|
||||||
{
|
{
|
||||||
Map.Entry entry = (Entry) it.next();
|
|
||||||
String key = (String) entry.getKey();
|
public Object transform( Object input )
|
||||||
RepositoryConfiguration repoConfig = (RepositoryConfiguration) entry.getValue();
|
{
|
||||||
ArchivaRepository repository = ArchivaConfigurationAdaptor.toArchivaRepository( repoConfig );
|
if ( input instanceof RepositoryConfiguration )
|
||||||
this.repositoryMap.put( key, repository );
|
{
|
||||||
}
|
return ArchivaConfigurationAdaptor.toArchivaRepository( (RepositoryConfiguration) input );
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CollectionUtils.transform( repos, toArchivaRepository );
|
||||||
|
|
||||||
|
this.localIndexedRepositories.addAll( repos );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize()
|
public void initialize()
|
||||||
throws InitializationException
|
throws InitializationException
|
||||||
{
|
{
|
||||||
initRepositoryMap();
|
initRepositories();
|
||||||
configuration.addChangeListener( this );
|
configuration.addChangeListener( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.apache.maven.archiva.indexer.search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchResultHit
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class SearchResultHit
|
||||||
|
{
|
||||||
|
// The (optional) context for this result.
|
||||||
|
private String context;
|
||||||
|
|
||||||
|
// Basic hit, direct to non-artifact resource.
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
// Advanced hit, reference to groupId.
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
// Advanced hit, reference to artifactId.
|
||||||
|
private String artifactId;
|
||||||
|
|
||||||
|
// Advanced hit, if artifact, all versions of artifact
|
||||||
|
private List artifacts = new ArrayList();
|
||||||
|
|
||||||
|
public String getContext()
|
||||||
|
{
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext( String context )
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl()
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl( String url )
|
||||||
|
{
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArtifactId()
|
||||||
|
{
|
||||||
|
return artifactId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArtifactId( String artifactId )
|
||||||
|
{
|
||||||
|
this.artifactId = artifactId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addArtifact( ArchivaArtifact artifact )
|
||||||
|
{
|
||||||
|
this.artifacts.add( artifact );
|
||||||
|
|
||||||
|
if ( StringUtils.isBlank( this.groupId ) )
|
||||||
|
{
|
||||||
|
this.groupId = artifact.getGroupId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( StringUtils.isBlank( this.artifactId ) )
|
||||||
|
{
|
||||||
|
this.artifactId = artifact.getArtifactId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getArtifacts()
|
||||||
|
{
|
||||||
|
return artifacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArtifacts( List artifacts )
|
||||||
|
{
|
||||||
|
this.artifacts = artifacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId()
|
||||||
|
{
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId( String groupId )
|
||||||
|
{
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.apache.maven.archiva.indexer.search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchResultLimits - used to provide the search some limits on how the results are returned.
|
||||||
|
* This can provide paging for the
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class SearchResultLimits
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constant to use for {@link #setSelectedPage(int)} to indicate a desire to get ALL PAGES.
|
||||||
|
* USE WITH CAUTION!!
|
||||||
|
*/
|
||||||
|
public static final int ALL_PAGES = ( -1 );
|
||||||
|
|
||||||
|
private int pageSize = 30;
|
||||||
|
|
||||||
|
private int selectedPage = 0;
|
||||||
|
|
||||||
|
public SearchResultLimits( int selectedPage )
|
||||||
|
{
|
||||||
|
this.selectedPage = selectedPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPageSize()
|
||||||
|
{
|
||||||
|
return pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set page size for maximum # of hits to return per page.
|
||||||
|
*
|
||||||
|
* @param pageSize size of page by # of hits. (maximum value is 200)
|
||||||
|
*/
|
||||||
|
public void setPageSize( int pageSize )
|
||||||
|
{
|
||||||
|
this.pageSize = Math.min( 200, pageSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedPage()
|
||||||
|
{
|
||||||
|
return selectedPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedPage( int selectedPage )
|
||||||
|
{
|
||||||
|
this.selectedPage = selectedPage;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,17 @@ package org.apache.maven.archiva.indexer.search;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord;
|
||||||
|
import org.apache.maven.archiva.indexer.filecontent.FileContentRecord;
|
||||||
|
import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord;
|
||||||
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SearchResults
|
* SearchResults
|
||||||
|
@ -32,35 +41,106 @@ public class SearchResults
|
||||||
{
|
{
|
||||||
private List repositories = new ArrayList();
|
private List repositories = new ArrayList();
|
||||||
|
|
||||||
private List contentHits = new ArrayList();
|
private Map hits = new HashMap();
|
||||||
|
|
||||||
private List bytecodeHits = new ArrayList();
|
private int totalHits;
|
||||||
|
|
||||||
private List hashcodeHits = new ArrayList();
|
private SearchResultLimits limits;
|
||||||
|
|
||||||
public SearchResults()
|
public SearchResults()
|
||||||
{
|
{
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty()
|
public void addHit( LuceneRepositoryContentRecord record )
|
||||||
{
|
{
|
||||||
return ( bytecodeHits.isEmpty() && hashcodeHits.isEmpty() && contentHits.isEmpty() );
|
if ( record instanceof FileContentRecord )
|
||||||
|
{
|
||||||
|
FileContentRecord filecontent = (FileContentRecord) record;
|
||||||
|
addFileContentHit( filecontent );
|
||||||
|
}
|
||||||
|
else if ( record instanceof HashcodesRecord )
|
||||||
|
{
|
||||||
|
HashcodesRecord hashcodes = (HashcodesRecord) record;
|
||||||
|
addHashcodeHit( hashcodes );
|
||||||
|
}
|
||||||
|
else if ( record instanceof BytecodeRecord )
|
||||||
|
{
|
||||||
|
BytecodeRecord bytecode = (BytecodeRecord) record;
|
||||||
|
addBytecodeHit( bytecode );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getBytecodeHits()
|
private void addBytecodeHit( BytecodeRecord bytecode )
|
||||||
{
|
{
|
||||||
return bytecodeHits;
|
String key = toKey( bytecode.getArtifact() );
|
||||||
|
|
||||||
|
SearchResultHit hit = (SearchResultHit) this.hits.get( key );
|
||||||
|
|
||||||
|
if ( hit == null )
|
||||||
|
{
|
||||||
|
hit = new SearchResultHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.addArtifact( bytecode.getArtifact() );
|
||||||
|
hit.setContext( null ); // TODO: provide context on why this is a valuable hit.
|
||||||
|
|
||||||
|
this.hits.put( key, hit );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getContentHits()
|
private String toKey( ArchivaArtifact artifact )
|
||||||
{
|
{
|
||||||
return contentHits;
|
StringBuffer key = new StringBuffer();
|
||||||
|
|
||||||
|
key.append( StringUtils.defaultString( artifact.getGroupId() ) ).append( ":" );
|
||||||
|
key.append( StringUtils.defaultString( artifact.getArtifactId() ) );
|
||||||
|
|
||||||
|
return key.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getHashcodeHits()
|
private void addHashcodeHit( HashcodesRecord hashcodes )
|
||||||
{
|
{
|
||||||
return hashcodeHits;
|
String key = toKey( hashcodes.getArtifact() );
|
||||||
|
|
||||||
|
SearchResultHit hit = (SearchResultHit) this.hits.get( key );
|
||||||
|
|
||||||
|
if ( hit == null )
|
||||||
|
{
|
||||||
|
hit = new SearchResultHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.addArtifact( hashcodes.getArtifact() );
|
||||||
|
hit.setContext( null ); // TODO: provide context on why this is a valuable hit.
|
||||||
|
|
||||||
|
this.hits.put( key, hit );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFileContentHit( FileContentRecord filecontent )
|
||||||
|
{
|
||||||
|
String key = filecontent.getPrimaryKey();
|
||||||
|
|
||||||
|
SearchResultHit hit = (SearchResultHit) this.hits.get( key );
|
||||||
|
|
||||||
|
if ( hit == null )
|
||||||
|
{
|
||||||
|
// Only need to worry about this hit if it is truely new.
|
||||||
|
hit = new SearchResultHit();
|
||||||
|
|
||||||
|
hit.setUrl( filecontent.getRepositoryId() + "/" + filecontent.getFilename() );
|
||||||
|
hit.setContext( null ); // TODO: handle context + highlight later.
|
||||||
|
|
||||||
|
this.hits.put( key, hit );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of {@link SearchResultHit} objects.
|
||||||
|
*
|
||||||
|
* @return the list of {@link SearchResultHit} objects.
|
||||||
|
*/
|
||||||
|
public List getHits()
|
||||||
|
{
|
||||||
|
return new ArrayList( hits.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getRepositories()
|
public List getRepositories()
|
||||||
|
@ -68,23 +148,33 @@ public class SearchResults
|
||||||
return repositories;
|
return repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBytecodeHits( List bytecodeHits )
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
this.bytecodeHits = bytecodeHits;
|
return hits.isEmpty();
|
||||||
}
|
|
||||||
|
|
||||||
public void setContentHits( List contentHits )
|
|
||||||
{
|
|
||||||
this.contentHits = contentHits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHashcodeHits( List hashcodeHits )
|
|
||||||
{
|
|
||||||
this.hashcodeHits = hashcodeHits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRepositories( List repositories )
|
public void setRepositories( List repositories )
|
||||||
{
|
{
|
||||||
this.repositories = repositories;
|
this.repositories = repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SearchResultLimits getLimits()
|
||||||
|
{
|
||||||
|
return limits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLimits( SearchResultLimits limits )
|
||||||
|
{
|
||||||
|
this.limits = limits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalHits()
|
||||||
|
{
|
||||||
|
return totalHits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalHits( int totalHits )
|
||||||
|
{
|
||||||
|
this.totalHits = totalHits;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,19 @@ package org.apache.maven.archiva.indexer;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.queryParser.ParseException;
|
import org.apache.lucene.queryParser.ParseException;
|
||||||
import org.apache.lucene.queryParser.QueryParser;
|
import org.apache.lucene.queryParser.QueryParser;
|
||||||
|
import org.apache.lucene.search.Hit;
|
||||||
|
import org.apache.lucene.search.Hits;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.Searcher;
|
||||||
import org.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
|
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -39,13 +44,15 @@ import junit.framework.ComparisonFailure;
|
||||||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSearchTestCase extends AbstractIndexerTestCase
|
public abstract class AbstractSearchTestCase
|
||||||
|
extends AbstractIndexerTestCase
|
||||||
{
|
{
|
||||||
protected Map records;
|
protected Map records;
|
||||||
|
|
||||||
protected abstract Map createSampleRecordsMap();
|
protected abstract Map createSampleRecordsMap();
|
||||||
|
|
||||||
protected void setUp() throws Exception
|
protected void setUp()
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
|
@ -59,7 +66,8 @@ public abstract class AbstractSearchTestCase extends AbstractIndexerTestCase
|
||||||
return new TermQuery( new Term( field, value ) );
|
return new TermQuery( new Term( field, value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Query createMatchQuery( String field, String value ) throws ParseException
|
protected Query createMatchQuery( String field, String value )
|
||||||
|
throws ParseException
|
||||||
{
|
{
|
||||||
QueryParser queryParser = new QueryParser( field, indexHandlers.getAnalyzer() );
|
QueryParser queryParser = new QueryParser( field, indexHandlers.getAnalyzer() );
|
||||||
queryParser.setLowercaseExpandedTerms( true );
|
queryParser.setLowercaseExpandedTerms( true );
|
||||||
|
@ -81,8 +89,8 @@ public abstract class AbstractSearchTestCase extends AbstractIndexerTestCase
|
||||||
if ( expectedKeys.length != actualResults.size() )
|
if ( expectedKeys.length != actualResults.size() )
|
||||||
{
|
{
|
||||||
dumpResults( actualResults );
|
dumpResults( actualResults );
|
||||||
throw new ComparisonFailure( "Results count", String.valueOf( expectedKeys.length ),
|
throw new ComparisonFailure( "Results count", String.valueOf( expectedKeys.length ), String
|
||||||
String.valueOf( actualResults.size() ) );
|
.valueOf( actualResults.size() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals( "Results count", expectedKeys.length, actualResults.size() );
|
assertEquals( "Results count", expectedKeys.length, actualResults.size() );
|
||||||
|
@ -96,8 +104,7 @@ public abstract class AbstractSearchTestCase extends AbstractIndexerTestCase
|
||||||
{
|
{
|
||||||
dumpResults( actualResults );
|
dumpResults( actualResults );
|
||||||
fail( "Expected record <" + key
|
fail( "Expected record <" + key
|
||||||
+ "> not in records map (smack the unit test developer, tell them to fix method "
|
+ "> not in records map (smack the unit test developer, tell them to fix method " + getName() + ")" );
|
||||||
+ getName() + ")" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !actualResults.contains( record ) )
|
if ( !actualResults.contains( record ) )
|
||||||
|
@ -133,31 +140,56 @@ public abstract class AbstractSearchTestCase extends AbstractIndexerTestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertQueryExactMatchNoResults( String key, String term ) throws RepositoryIndexSearchException
|
protected void assertQueryExactMatchNoResults( String key, String term )
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
Query query = createExactMatchQuery( key, term );
|
Query query = createExactMatchQuery( key, term );
|
||||||
List results = index.search( new LuceneQuery( query ) );
|
List results = search( query );
|
||||||
assertNoResults( results );
|
assertNoResults( results );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertQueryExactMatch( String key, String names[], String term ) throws RepositoryIndexSearchException
|
protected void assertQueryExactMatch( String key, String names[], String term )
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
Query query = createExactMatchQuery( key, term );
|
Query query = createExactMatchQuery( key, term );
|
||||||
List results = index.search( new LuceneQuery( query ) );
|
List results = search( query );
|
||||||
assertResults( names, results );
|
assertResults( names, results );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertQueryMatch( String key, String names[], String term ) throws Exception
|
protected void assertQueryMatch( String key, String names[], String term )
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
Query query = createMatchQuery( key, term );
|
Query query = createMatchQuery( key, term );
|
||||||
List results = index.search( new LuceneQuery( query ) );
|
List results = search( query );
|
||||||
assertResults( names, results );
|
assertResults( names, results );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertQueryMatchNoResults( String key, String term ) throws Exception
|
protected void assertQueryMatchNoResults( String key, String term )
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
Query query = createMatchQuery( key, term );
|
Query query = createMatchQuery( key, term );
|
||||||
List results = index.search( new LuceneQuery( query ) );
|
|
||||||
|
List results = search( query );
|
||||||
|
|
||||||
assertNoResults( results );
|
assertNoResults( results );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List search( Query query )
|
||||||
|
throws RepositoryIndexSearchException, IOException, java.text.ParseException
|
||||||
|
{
|
||||||
|
Searcher searcher = (Searcher) index.getSearchable();; // this shouldn't cause a problem.
|
||||||
|
|
||||||
|
Hits hits = searcher.search( query );
|
||||||
|
|
||||||
|
List results = new ArrayList();
|
||||||
|
Iterator it = hits.iterator();
|
||||||
|
while ( it.hasNext() )
|
||||||
|
{
|
||||||
|
Hit hit = (Hit) it.next();
|
||||||
|
Document doc = hit.getDocument();
|
||||||
|
LuceneRepositoryContentRecord record = index.getEntryConverter().convert( doc );
|
||||||
|
results.add( record );
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class AllTests
|
||||||
suite.addTest( org.apache.maven.archiva.indexer.bytecode.AllTests.suite() );
|
suite.addTest( org.apache.maven.archiva.indexer.bytecode.AllTests.suite() );
|
||||||
suite.addTest( org.apache.maven.archiva.indexer.hashcodes.AllTests.suite() );
|
suite.addTest( org.apache.maven.archiva.indexer.hashcodes.AllTests.suite() );
|
||||||
suite.addTest( org.apache.maven.archiva.indexer.query.AllTests.suite() );
|
suite.addTest( org.apache.maven.archiva.indexer.query.AllTests.suite() );
|
||||||
|
suite.addTest( org.apache.maven.archiva.indexer.search.AllTests.suite() );
|
||||||
//$JUnit-END$
|
//$JUnit-END$
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,7 @@ import org.apache.maven.archiva.indexer.AbstractSearchTestCase;
|
||||||
import org.apache.maven.archiva.indexer.ArtifactKeys;
|
import org.apache.maven.archiva.indexer.ArtifactKeys;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneIndexHandlers;
|
import org.apache.maven.archiva.indexer.lucene.LuceneIndexHandlers;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
|
|
||||||
import org.apache.maven.archiva.model.ArchivaArtifact;
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
import org.apache.maven.archiva.model.ArchivaRepository;
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
@ -72,96 +70,97 @@ public class BytecodeSearchTest extends AbstractSearchTestCase
|
||||||
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
||||||
File dumpFile = getDumpFile( artifact );
|
File dumpFile = getDumpFile( artifact );
|
||||||
BytecodeRecord record = BytecodeRecordLoader.loadRecord( dumpFile, artifact );
|
BytecodeRecord record = BytecodeRecordLoader.loadRecord( dumpFile, artifact );
|
||||||
|
record.setRepositoryId( "test-repo" );
|
||||||
records.put( entry.getKey(), record );
|
records.put( entry.getKey(), record );
|
||||||
}
|
}
|
||||||
|
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionSimple() throws RepositoryIndexSearchException
|
public void testExactMatchVersionSimple() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "archiva-common" }, "1.0" );
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "archiva-common" }, "1.0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "continuum-webapp" }, "1.0.3-SNAPSHOT" );
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "continuum-webapp" }, "1.0.3-SNAPSHOT" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionAlphaSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionAlphaSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "redback-authorization-open" },
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "redback-authorization-open" },
|
||||||
"1.0-alpha-1-SNAPSHOT" );
|
"1.0-alpha-1-SNAPSHOT" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionTimestampedSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionTimestampedSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "wagon-provider-api" },
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "wagon-provider-api" },
|
||||||
"1.0-beta-3-20070209.213958-2" );
|
"1.0-beta-3-20070209.213958-2" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchVersionInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.VERSION_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.VERSION_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdOrgApacheMavenArchiva() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdOrgApacheMavenArchiva() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "archiva-common" },
|
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "archiva-common" },
|
||||||
"org.apache.maven.archiva" );
|
"org.apache.maven.archiva" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdOrgApacheMaven() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdOrgApacheMaven() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "maven-archetype-simple" },
|
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "maven-archetype-simple" },
|
||||||
"org.apache.maven" );
|
"org.apache.maven" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.GROUPID_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.GROUPID_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdArchivaCommon() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdArchivaCommon() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "archiva-common" }, "archiva-common" );
|
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "archiva-common" }, "archiva-common" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdTestNg() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdTestNg() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "testng" }, "testng" );
|
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "testng" }, "testng" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.ARTIFACTID_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.ARTIFACTID_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchTypeJar() throws RepositoryIndexSearchException
|
public void testExactMatchTypeJar() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "archiva-common", "redback-authorization-open",
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "archiva-common", "redback-authorization-open",
|
||||||
"testng", "wagon-provider-api" } ), "jar" );
|
"testng", "wagon-provider-api" } ), "jar" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchTypeWar() throws RepositoryIndexSearchException
|
public void testExactMatchTypeWar() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "continuum-webapp" } ), "war" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "continuum-webapp" } ), "war" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Fix 'maven-plugin' type
|
/* TODO: Fix 'maven-plugin' type
|
||||||
public void testExactMatchTypePlugin() throws RepositoryIndexSearchException
|
public void testExactMatchTypePlugin() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-help-plugin" } ), "maven-plugin" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-help-plugin" } ), "maven-plugin" );
|
||||||
} */
|
} */
|
||||||
|
|
||||||
/* TODO: Fix 'maven-archetype' type
|
/* TODO: Fix 'maven-archetype' type
|
||||||
public void testExactMatchTypeArchetype() throws RepositoryIndexSearchException
|
public void testExactMatchTypeArchetype() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-archetype-simple" } ), "maven-archetype" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-archetype-simple" } ), "maven-archetype" );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void testExactMatchTypeInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchTypeInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.TYPE, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.TYPE, "foo" );
|
||||||
}
|
}
|
||||||
|
@ -250,7 +249,7 @@ public class BytecodeSearchTest extends AbstractSearchTestCase
|
||||||
BooleanQuery bQuery = new BooleanQuery();
|
BooleanQuery bQuery = new BooleanQuery();
|
||||||
bQuery.add( new MatchAllDocsQuery(), BooleanClause.Occur.MUST );
|
bQuery.add( new MatchAllDocsQuery(), BooleanClause.Occur.MUST );
|
||||||
bQuery.add( createMatchQuery( ArtifactKeys.CLASSIFIER, "jdk15" ), BooleanClause.Occur.MUST_NOT );
|
bQuery.add( createMatchQuery( ArtifactKeys.CLASSIFIER, "jdk15" ), BooleanClause.Occur.MUST_NOT );
|
||||||
List results = index.search( new LuceneQuery( bQuery ) );
|
List results = search( bQuery );
|
||||||
|
|
||||||
assertResults( new String[] { "archiva-common", "continuum-webapp", "redback-authorization-open",
|
assertResults( new String[] { "archiva-common", "continuum-webapp", "redback-authorization-open",
|
||||||
"daytrader-ear", "maven-archetype-simple", "maven-help-plugin", "wagon-provider-api" }, results );
|
"daytrader-ear", "maven-archetype-simple", "maven-help-plugin", "wagon-provider-api" }, results );
|
||||||
|
|
|
@ -55,6 +55,7 @@ public class HashcodesIndexTest extends AbstractIndexCreationTestCase
|
||||||
ArchivaArtifact artifact = new ArchivaArtifact( "com.foo", "projfoo", "1.0", "", "jar" );
|
ArchivaArtifact artifact = new ArchivaArtifact( "com.foo", "projfoo", "1.0", "", "jar" );
|
||||||
|
|
||||||
HashcodesRecord record = new HashcodesRecord();
|
HashcodesRecord record = new HashcodesRecord();
|
||||||
|
record.setRepositoryId( "test-repo" );
|
||||||
record.setArtifact( artifact );
|
record.setArtifact( artifact );
|
||||||
|
|
||||||
artifact.getModel().setChecksumSHA1( "c66f18bf192cb613fc2febb4da541a34133eedc2" );
|
artifact.getModel().setChecksumSHA1( "c66f18bf192cb613fc2febb4da541a34133eedc2" );
|
||||||
|
|
|
@ -26,9 +26,7 @@ import org.apache.maven.archiva.indexer.AbstractSearchTestCase;
|
||||||
import org.apache.maven.archiva.indexer.ArtifactKeys;
|
import org.apache.maven.archiva.indexer.ArtifactKeys;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneIndexHandlers;
|
import org.apache.maven.archiva.indexer.lucene.LuceneIndexHandlers;
|
||||||
import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
|
|
||||||
import org.apache.maven.archiva.model.ArchivaArtifact;
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
import org.apache.maven.archiva.model.ArchivaRepository;
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
@ -72,118 +70,119 @@ public class HashcodesSearchTest extends AbstractSearchTestCase
|
||||||
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
||||||
File dumpFile = getDumpFile( artifact );
|
File dumpFile = getDumpFile( artifact );
|
||||||
HashcodesRecord record = HashcodesRecordLoader.loadRecord( dumpFile, artifact );
|
HashcodesRecord record = HashcodesRecordLoader.loadRecord( dumpFile, artifact );
|
||||||
|
record.setRepositoryId( "test-repo" );
|
||||||
records.put( entry.getKey(), record );
|
records.put( entry.getKey(), record );
|
||||||
}
|
}
|
||||||
|
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionSimple() throws RepositoryIndexSearchException
|
public void testExactMatchVersionSimple() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "archiva-common" }, "1.0" );
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "archiva-common" }, "1.0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "continuum-webapp" }, "1.0.3-SNAPSHOT" );
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "continuum-webapp" }, "1.0.3-SNAPSHOT" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionAlphaSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionAlphaSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "redback-authorization-open" },
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "redback-authorization-open" },
|
||||||
"1.0-alpha-1-SNAPSHOT" );
|
"1.0-alpha-1-SNAPSHOT" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionTimestampedSnapshot() throws RepositoryIndexSearchException
|
public void testExactMatchVersionTimestampedSnapshot() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "wagon-provider-api" },
|
assertQueryExactMatch( ArtifactKeys.VERSION_EXACT, new String[] { "wagon-provider-api" },
|
||||||
"1.0-beta-3-20070209.213958-2" );
|
"1.0-beta-3-20070209.213958-2" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchVersionInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchVersionInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.VERSION_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.VERSION_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdOrgApacheMavenArchiva() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdOrgApacheMavenArchiva() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "archiva-common" },
|
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "archiva-common" },
|
||||||
"org.apache.maven.archiva" );
|
"org.apache.maven.archiva" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdOrgApacheMaven() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdOrgApacheMaven() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "maven-archetype-simple" },
|
assertQueryExactMatch( ArtifactKeys.GROUPID_EXACT, new String[] { "maven-archetype-simple" },
|
||||||
"org.apache.maven" );
|
"org.apache.maven" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchGroupIdInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchGroupIdInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.GROUPID_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.GROUPID_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdArchivaCommon() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdArchivaCommon() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "archiva-common" }, "archiva-common" );
|
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "archiva-common" }, "archiva-common" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdTestNg() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdTestNg() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "testng" }, "testng" );
|
assertQueryExactMatch( ArtifactKeys.ARTIFACTID_EXACT, new String[] { "testng" }, "testng" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchArtifactIdInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchArtifactIdInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.ARTIFACTID_EXACT, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.ARTIFACTID_EXACT, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchTypeJar() throws RepositoryIndexSearchException
|
public void testExactMatchTypeJar() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "archiva-common", "redback-authorization-open",
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "archiva-common", "redback-authorization-open",
|
||||||
"testng", "wagon-provider-api" } ), "jar" );
|
"testng", "wagon-provider-api" } ), "jar" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchTypeWar() throws RepositoryIndexSearchException
|
public void testExactMatchTypeWar() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "continuum-webapp" } ), "war" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "continuum-webapp" } ), "war" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Fix 'maven-plugin' type
|
/* TODO: Fix 'maven-plugin' type
|
||||||
public void testExactMatchTypePlugin() throws RepositoryIndexSearchException
|
public void testExactMatchTypePlugin() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-help-plugin" } ), "maven-plugin" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-help-plugin" } ), "maven-plugin" );
|
||||||
} */
|
} */
|
||||||
|
|
||||||
/* TODO: Fix 'maven-archetype' type
|
/* TODO: Fix 'maven-archetype' type
|
||||||
public void testExactMatchTypeArchetype() throws RepositoryIndexSearchException
|
public void testExactMatchTypeArchetype() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-archetype-simple" } ), "maven-archetype" );
|
assertQueryExactMatch( ArtifactKeys.TYPE, ( new String[] { "maven-archetype-simple" } ), "maven-archetype" );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void testExactMatchTypeInvalid() throws RepositoryIndexSearchException
|
public void testExactMatchTypeInvalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( ArtifactKeys.TYPE, "foo" );
|
assertQueryExactMatchNoResults( ArtifactKeys.TYPE, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchMd5() throws RepositoryIndexSearchException
|
public void testExactMatchMd5() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( HashcodesKeys.MD5, ( new String[] { "redback-authorization-open" } ),
|
assertQueryExactMatch( HashcodesKeys.MD5, ( new String[] { "redback-authorization-open" } ),
|
||||||
"f42047fe2e177ac04d0df7aa44d408be" );
|
"f42047fe2e177ac04d0df7aa44d408be" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchMd5Invalid() throws RepositoryIndexSearchException
|
public void testExactMatchMd5Invalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( HashcodesKeys.MD5, "foo" );
|
assertQueryExactMatchNoResults( HashcodesKeys.MD5, "foo" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchSha1() throws RepositoryIndexSearchException
|
public void testExactMatchSha1() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatch( HashcodesKeys.SHA1, ( new String[] { "archiva-common" } ),
|
assertQueryExactMatch( HashcodesKeys.SHA1, ( new String[] { "archiva-common" } ),
|
||||||
"c2635a1b38bd4520a6604664c04b2b3c32330864" );
|
"c2635a1b38bd4520a6604664c04b2b3c32330864" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExactMatchSha1Invalid() throws RepositoryIndexSearchException
|
public void testExactMatchSha1Invalid() throws Exception
|
||||||
{
|
{
|
||||||
assertQueryExactMatchNoResults( HashcodesKeys.SHA1, "foo" );
|
assertQueryExactMatchNoResults( HashcodesKeys.SHA1, "foo" );
|
||||||
}
|
}
|
||||||
|
@ -272,7 +271,7 @@ public class HashcodesSearchTest extends AbstractSearchTestCase
|
||||||
BooleanQuery bQuery = new BooleanQuery();
|
BooleanQuery bQuery = new BooleanQuery();
|
||||||
bQuery.add( new MatchAllDocsQuery(), BooleanClause.Occur.MUST );
|
bQuery.add( new MatchAllDocsQuery(), BooleanClause.Occur.MUST );
|
||||||
bQuery.add( createMatchQuery( ArtifactKeys.CLASSIFIER, "jdk15" ), BooleanClause.Occur.MUST_NOT );
|
bQuery.add( createMatchQuery( ArtifactKeys.CLASSIFIER, "jdk15" ), BooleanClause.Occur.MUST_NOT );
|
||||||
List results = index.search( new LuceneQuery( bQuery ) );
|
List results = search( bQuery );
|
||||||
|
|
||||||
assertResults( new String[] { "archiva-common", "continuum-webapp", "redback-authorization-open",
|
assertResults( new String[] { "archiva-common", "continuum-webapp", "redback-authorization-open",
|
||||||
"daytrader-ear", "maven-archetype-simple", "maven-help-plugin", "wagon-provider-api" }, results );
|
"daytrader-ear", "maven-archetype-simple", "maven-help-plugin", "wagon-provider-api" }, results );
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.apache.maven.archiva.indexer.search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AllTests - conveinence test suite for IDE users.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class AllTests
|
||||||
|
{
|
||||||
|
public static Test suite()
|
||||||
|
{
|
||||||
|
TestSuite suite = new TestSuite( "Test for org.apache.maven.archiva.indexer.search" );
|
||||||
|
//$JUnit-BEGIN$
|
||||||
|
suite.addTestSuite( DefaultCrossRepositorySearchTest.class );
|
||||||
|
//$JUnit-END$
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,6 +98,7 @@ public class BytecodeIndexPopulator
|
||||||
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
||||||
File dumpFile = getDumpFile( basedir, artifact );
|
File dumpFile = getDumpFile( basedir, artifact );
|
||||||
BytecodeRecord record = BytecodeRecordLoader.loadRecord( dumpFile, artifact );
|
BytecodeRecord record = BytecodeRecordLoader.loadRecord( dumpFile, artifact );
|
||||||
|
record.setRepositoryId( "test-repo" );
|
||||||
records.put( entry.getKey(), record );
|
records.put( entry.getKey(), record );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,16 @@ package org.apache.maven.archiva.indexer.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.lucene.search.Hits;
|
||||||
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.Searcher;
|
||||||
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
|
||||||
import org.apache.maven.archiva.indexer.MockConfiguration;
|
import org.apache.maven.archiva.indexer.MockConfiguration;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndex;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
|
||||||
|
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
||||||
import org.apache.maven.archiva.model.ArchivaRepository;
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
import org.codehaus.plexus.PlexusTestCase;
|
import org.codehaus.plexus.PlexusTestCase;
|
||||||
import org.codehaus.plexus.util.FileUtils;
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
|
@ -68,6 +73,7 @@ public class DefaultCrossRepositorySearchTest
|
||||||
repoConfig.setName( repository.getModel().getName() );
|
repoConfig.setName( repository.getModel().getName() );
|
||||||
repoConfig.setUrl( repository.getModel().getUrl() );
|
repoConfig.setUrl( repository.getModel().getUrl() );
|
||||||
repoConfig.setIndexDir( indexLocation.getAbsolutePath() );
|
repoConfig.setIndexDir( indexLocation.getAbsolutePath() );
|
||||||
|
repoConfig.setIndexed( true );
|
||||||
|
|
||||||
if ( indexLocation.exists() )
|
if ( indexLocation.exists() )
|
||||||
{
|
{
|
||||||
|
@ -84,10 +90,27 @@ public class DefaultCrossRepositorySearchTest
|
||||||
// Now populate them.
|
// Now populate them.
|
||||||
Map hashcodesMap = ( new HashcodesIndexPopulator() ).populate( new File( getBasedir() ) );
|
Map hashcodesMap = ( new HashcodesIndexPopulator() ).populate( new File( getBasedir() ) );
|
||||||
indexHashcode.indexRecords( hashcodesMap.values() );
|
indexHashcode.indexRecords( hashcodesMap.values() );
|
||||||
|
assertEquals( "Hashcode Key Count", hashcodesMap.size(), indexHashcode.getAllRecordKeys().size() );
|
||||||
|
assertRecordCount( indexHashcode, hashcodesMap.size() );
|
||||||
|
|
||||||
Map bytecodeMap = ( new BytecodeIndexPopulator() ).populate( new File( getBasedir() ) );
|
Map bytecodeMap = ( new BytecodeIndexPopulator() ).populate( new File( getBasedir() ) );
|
||||||
indexBytecode.indexRecords( bytecodeMap.values() );
|
indexBytecode.indexRecords( bytecodeMap.values() );
|
||||||
|
assertEquals( "Bytecode Key Count", bytecodeMap.size(), indexBytecode.getAllRecordKeys().size() );
|
||||||
|
assertRecordCount( indexBytecode, bytecodeMap.size() );
|
||||||
|
|
||||||
Map contentMap = ( new FileContentIndexPopulator() ).populate( new File( getBasedir() ) );
|
Map contentMap = ( new FileContentIndexPopulator() ).populate( new File( getBasedir() ) );
|
||||||
indexContents.indexRecords( contentMap.values() );
|
indexContents.indexRecords( contentMap.values() );
|
||||||
|
assertEquals( "File Content Key Count", contentMap.size(), indexContents.getAllRecordKeys().size() );
|
||||||
|
assertRecordCount( indexContents, contentMap.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertRecordCount( RepositoryContentIndex index, int expectedCount )
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
Query query = new MatchAllDocsQuery();
|
||||||
|
Searcher searcher = (Searcher) index.getSearchable();
|
||||||
|
Hits hits = searcher.search( query );
|
||||||
|
assertEquals( "Expected Record Count for " + index.getId(), expectedCount, hits.length() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private CrossRepositorySearch lookupCrossRepositorySearch()
|
private CrossRepositorySearch lookupCrossRepositorySearch()
|
||||||
|
@ -98,34 +121,47 @@ public class DefaultCrossRepositorySearchTest
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchTerm()
|
public void testSearchTerm_Org()
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
CrossRepositorySearch search = lookupCrossRepositorySearch();
|
CrossRepositorySearch search = lookupCrossRepositorySearch();
|
||||||
|
|
||||||
SearchResults results = search.searchForTerm( "org" );
|
SearchResultLimits limits = new SearchResultLimits( 0 );
|
||||||
assertHitCounts( 1, 8, 8, 1, results );
|
limits.setPageSize( 20 );
|
||||||
|
|
||||||
results = search.searchForTerm( "junit" );
|
SearchResults results = search.searchForTerm( "org", limits );
|
||||||
assertHitCounts( 1, 1, 0, 1, results );
|
assertResults( 1, 7, results );
|
||||||
|
|
||||||
results = search.searchForTerm( "monosodium" );
|
|
||||||
assertHitCounts( 1, 0, 0, 0, results );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertHitCounts( int repoCount, int bytecodeCount, int hashcodeCount, int contentCount,
|
public void testSearchTerm_Junit()
|
||||||
SearchResults results )
|
throws Exception
|
||||||
|
{
|
||||||
|
CrossRepositorySearch search = lookupCrossRepositorySearch();
|
||||||
|
|
||||||
|
SearchResultLimits limits = new SearchResultLimits( 0 );
|
||||||
|
limits.setPageSize( 20 );
|
||||||
|
|
||||||
|
SearchResults results = search.searchForTerm( "junit", limits );
|
||||||
|
assertResults( 1, 3, results );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSearchInvalidTerm()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
CrossRepositorySearch search = lookupCrossRepositorySearch();
|
||||||
|
|
||||||
|
SearchResultLimits limits = new SearchResultLimits( 0 );
|
||||||
|
limits.setPageSize( 20 );
|
||||||
|
|
||||||
|
SearchResults results = search.searchForTerm( "monosodium", limits );
|
||||||
|
assertResults( 1, 0, results );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertResults( int repoCount, int hitCount, SearchResults results )
|
||||||
{
|
{
|
||||||
assertNotNull( "Search Results should not be null.", results );
|
assertNotNull( "Search Results should not be null.", results );
|
||||||
assertEquals( "Repository Hits", repoCount, results.getRepositories().size() );
|
assertEquals( "Repository Hits", repoCount, results.getRepositories().size() );
|
||||||
|
|
||||||
if ( ( bytecodeCount != results.getBytecodeHits().size() )
|
assertEquals( "Search Result Hits", hitCount, results.getHits().size() );
|
||||||
|| ( hashcodeCount != results.getHashcodeHits().size() )
|
|
||||||
/* || ( contentCount != results.getContentHits().size() ) */ )
|
|
||||||
{
|
|
||||||
fail( "Failed to get expected results hit count. Expected: (bytecode,hashcode,content) <" + bytecodeCount
|
|
||||||
+ "," + hashcodeCount + "," + contentCount + ">, but got <" + results.getBytecodeHits().size() + ","
|
|
||||||
+ results.getHashcodeHits().size() + "," + results.getContentHits().size() + "> instead." );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,18 @@ public class FileContentIndexPopulator
|
||||||
|
|
||||||
File repoDir = new File( basedir, "src/test/managed-repository" );
|
File repoDir = new File( basedir, "src/test/managed-repository" );
|
||||||
|
|
||||||
map.put( "parent-pom-1",
|
String prefix = "org/apache/maven/archiva/record/";
|
||||||
createFileContentRecord( repoDir, "org/apache/maven/archiva/record/parent-pom/1/parent-pom-1.pom" ) );
|
|
||||||
|
map.put( "parent-pom-1", createFileContentRecord( repoDir, prefix + "parent-pom/1/parent-pom-1.pom" ) );
|
||||||
|
map.put( "child-pom-1.0-SNAPSHOT", createFileContentRecord( repoDir, prefix
|
||||||
|
+ "test-child-pom/1.0-SNAPSHOT/test-child-pom-1.0-20060728.121314-1.pom" ) );
|
||||||
|
map.put( "test-archetype-1.0", createFileContentRecord( repoDir, prefix
|
||||||
|
+ "test-archetype/1.0/test-archetype-1.0.pom" ) );
|
||||||
|
map.put( "test-jar-and-pom-1.0-alpha-1", createFileContentRecord( repoDir, prefix
|
||||||
|
+ "test-jar-and-pom/1.0-alpha-1/test-jar-and-pom-1.0-alpha-1.pom" ) );
|
||||||
|
map.put( "test-plugin-1.0", createFileContentRecord( repoDir, prefix + "test-plugin/1.0/test-plugin-1.0.pom" ) );
|
||||||
|
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" ) );
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +75,8 @@ public class FileContentIndexPopulator
|
||||||
}
|
}
|
||||||
|
|
||||||
FileContentRecord record = new FileContentRecord();
|
FileContentRecord record = new FileContentRecord();
|
||||||
record.setFile( pathToFile );
|
record.setRepositoryId( "test-repo" );
|
||||||
|
record.setFilename( path );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class HashcodesIndexPopulator
|
||||||
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue();
|
||||||
File dumpFile = getDumpFile( basedir, artifact );
|
File dumpFile = getDumpFile( basedir, artifact );
|
||||||
HashcodesRecord record = HashcodesRecordLoader.loadRecord( dumpFile, artifact );
|
HashcodesRecord record = HashcodesRecordLoader.loadRecord( dumpFile, artifact );
|
||||||
|
record.setRepositoryId( "test-repo" );
|
||||||
records.put( entry.getKey(), record );
|
records.put( entry.getKey(), record );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||||
|
|
||||||
|
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||||
|
|
||||||
|
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||||
|
<param name="Target" value="System.out"/>
|
||||||
|
<layout class="org.apache.log4j.PatternLayout">
|
||||||
|
<param name="ConversionPattern" value="%d [%t] %-5p %-30c{1} - %m%n"/>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Help identify bugs during testing -->
|
||||||
|
<logger name="org.apache.maven">
|
||||||
|
<level value="debug"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="org.codehaus.plexus.security">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<!-- squelch noisy objects (for now) -->
|
||||||
|
<logger name="org.codehaus.plexus.mailsender.MailSender">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="org.quartz">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="org.apache.jasper">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="com.opensymphony.xwork">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="com.opensymphony.webwork">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="org.codehaus.plexus.PlexusContainer">
|
||||||
|
<level value="info"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="JPOX">
|
||||||
|
<level value="warn"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="JPOX.MetaData">
|
||||||
|
<level value="error"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="JPOX.RDBMS.SQL">
|
||||||
|
<level value="error"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="SQL">
|
||||||
|
<level value="error"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="freemarker">
|
||||||
|
<level value="warn"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="org.codehaus.plexus.component.manager.ClassicSingletonComponentManager">
|
||||||
|
<level value="error"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<root>
|
||||||
|
<priority value="debug" />
|
||||||
|
<appender-ref ref="console" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</log4j:configuration>
|
|
@ -25,9 +25,29 @@
|
||||||
<description>DefaultCrossRepositorySearch</description>
|
<description>DefaultCrossRepositorySearch</description>
|
||||||
<requirements>
|
<requirements>
|
||||||
<requirement>
|
<requirement>
|
||||||
<role>org.apache.maven.archiva.indexer.RepositoryContentIndexFactory</role>
|
<role>org.apache.commons.collections.Transformer</role>
|
||||||
<role-hint>lucene</role-hint>
|
<role-hint>bytecode</role-hint>
|
||||||
<field-name>indexFactory</field-name>
|
<field-name>bytecodeIndexTransformer</field-name>
|
||||||
|
</requirement>
|
||||||
|
<requirement>
|
||||||
|
<role>org.apache.commons.collections.Transformer</role>
|
||||||
|
<role-hint>filecontent</role-hint>
|
||||||
|
<field-name>filecontentIndexTransformer</field-name>
|
||||||
|
</requirement>
|
||||||
|
<requirement>
|
||||||
|
<role>org.apache.commons.collections.Transformer</role>
|
||||||
|
<role-hint>hashcodes</role-hint>
|
||||||
|
<field-name>hashcodesIndexTransformer</field-name>
|
||||||
|
</requirement>
|
||||||
|
<requirement>
|
||||||
|
<role>org.apache.commons.collections.Transformer</role>
|
||||||
|
<role-hint>searchable</role-hint>
|
||||||
|
<field-name>searchableTransformer</field-name>
|
||||||
|
</requirement>
|
||||||
|
<requirement>
|
||||||
|
<role>org.apache.commons.collections.Predicate</role>
|
||||||
|
<role-hint>index-exists</role-hint>
|
||||||
|
<field-name>indexExistsPredicate</field-name>
|
||||||
</requirement>
|
</requirement>
|
||||||
<requirement>
|
<requirement>
|
||||||
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
|
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.apache.maven.archiva.model.functors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.collections.Predicate;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ManagedRepositoryPredicate
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ManagedRepositoryPredicate
|
||||||
|
implements Predicate
|
||||||
|
{
|
||||||
|
public static final Predicate INSTANCE = new ManagedRepositoryPredicate();
|
||||||
|
|
||||||
|
public static Predicate getInstance()
|
||||||
|
{
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean evaluate( Object object )
|
||||||
|
{
|
||||||
|
boolean satisfies = false;
|
||||||
|
|
||||||
|
if ( object instanceof ArchivaRepository )
|
||||||
|
{
|
||||||
|
ArchivaRepository repo = (ArchivaRepository) object;
|
||||||
|
return repo.isManaged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return satisfies;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,10 +19,12 @@ package org.apache.maven.archiva.web.action;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.lucene.queryParser.ParseException;
|
import org.apache.lucene.queryParser.ParseException;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexException;
|
import org.apache.maven.archiva.indexer.RepositoryIndexException;
|
||||||
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
|
||||||
import org.apache.maven.archiva.indexer.search.CrossRepositorySearch;
|
import org.apache.maven.archiva.indexer.search.CrossRepositorySearch;
|
||||||
|
import org.apache.maven.archiva.indexer.search.SearchResultLimits;
|
||||||
import org.apache.maven.archiva.indexer.search.SearchResults;
|
import org.apache.maven.archiva.indexer.search.SearchResults;
|
||||||
import org.codehaus.plexus.xwork.action.PlexusActionSupport;
|
import org.codehaus.plexus.xwork.action.PlexusActionSupport;
|
||||||
|
|
||||||
|
@ -41,11 +43,6 @@ public class SearchAction
|
||||||
*/
|
*/
|
||||||
private String q;
|
private String q;
|
||||||
|
|
||||||
/**
|
|
||||||
* The MD5 to search by.
|
|
||||||
*/
|
|
||||||
private String md5;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Search Results.
|
* The Search Results.
|
||||||
*/
|
*/
|
||||||
|
@ -65,13 +62,15 @@ public class SearchAction
|
||||||
{
|
{
|
||||||
/* TODO: give action message if indexing is in progress.
|
/* TODO: give action message if indexing is in progress.
|
||||||
* This should be based off a count of 'unprocessed' artifacts.
|
* This should be based off a count of 'unprocessed' artifacts.
|
||||||
* This (yet to be written) routine could tell the user that X artifacts are not yet
|
* This (yet to be written) routine could tell the user that X (unprocessed) artifacts are not yet
|
||||||
* present in the full text search.
|
* present in the full text search.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert q != null && q.length() != 0;
|
assert q != null && q.length() != 0;
|
||||||
|
|
||||||
results = crossRepoSearch.searchForTerm( q );
|
SearchResultLimits limits = new SearchResultLimits( 0 );
|
||||||
|
|
||||||
|
results = crossRepoSearch.searchForTerm( q, limits );
|
||||||
|
|
||||||
if ( results.isEmpty() )
|
if ( results.isEmpty() )
|
||||||
{
|
{
|
||||||
|
@ -80,7 +79,7 @@ public class SearchAction
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: filter / combine the artifacts by version? (is that even possible with non-artifact hits?)
|
// TODO: filter / combine the artifacts by version? (is that even possible with non-artifact hits?)
|
||||||
|
|
||||||
/* I don't think that we should, as I expect us to utilize the 'score' system in lucene in
|
/* I don't think that we should, as I expect us to utilize the 'score' system in lucene in
|
||||||
* the future to return relevant links better.
|
* the future to return relevant links better.
|
||||||
* I expect the lucene scoring system to take multiple hits on different areas of a single document
|
* I expect the lucene scoring system to take multiple hits on different areas of a single document
|
||||||
|
@ -96,18 +95,25 @@ public class SearchAction
|
||||||
{
|
{
|
||||||
// TODO: give action message if indexing is in progress
|
// TODO: give action message if indexing is in progress
|
||||||
|
|
||||||
assert md5 != null && md5.length() != 0;
|
if ( StringUtils.isBlank( q ) )
|
||||||
|
{
|
||||||
|
addActionError( "Unable to search for a blank checksum" );
|
||||||
|
return INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResultLimits limits = new SearchResultLimits( 0 );
|
||||||
|
|
||||||
|
results = crossRepoSearch.searchForChecksum( q, limits );
|
||||||
|
|
||||||
results = crossRepoSearch.searchForMd5( q );
|
|
||||||
|
|
||||||
if ( results.isEmpty() )
|
if ( results.isEmpty() )
|
||||||
{
|
{
|
||||||
addActionError( "No results found" );
|
addActionError( "No results found" );
|
||||||
return INPUT;
|
return INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( results.getHashcodeHits().size() == 1 )
|
if ( results.getHits().size() == 1 )
|
||||||
{
|
{
|
||||||
|
// 1 hit? return it's information directly!
|
||||||
return ARTIFACT;
|
return ARTIFACT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -131,13 +137,8 @@ public class SearchAction
|
||||||
this.q = q;
|
this.q = q;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMd5()
|
public SearchResults getResults()
|
||||||
{
|
{
|
||||||
return md5;
|
return results;
|
||||||
}
|
|
||||||
|
|
||||||
public void setMd5( String md5 )
|
|
||||||
{
|
|
||||||
this.md5 = md5;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
<%@ taglib uri="/webwork" prefix="ww" %>
|
<%@ taglib uri="/webwork" prefix="ww" %>
|
||||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
<%@ 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="my" tagdir="/WEB-INF/tags" %>
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
@ -39,48 +40,44 @@
|
||||||
<h1>Results</h1>
|
<h1>Results</h1>
|
||||||
|
|
||||||
<div id="resultsBox">
|
<div id="resultsBox">
|
||||||
<ww:set name="searchResults" value="searchResults"/>
|
<p>Hits: ${fn:length(results.hits)}</p>
|
||||||
<c:forEach items="${searchResults}" var="record" varStatus="i">
|
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="${empty results.hits}">
|
||||||
<h3 class="artifact-title">
|
<p>No results</p>
|
||||||
<my:showArtifactTitle groupId="${record.groupId}" artifactId="${record.artifactId}"
|
</c:when>
|
||||||
version="${record.version}"/>
|
<c:otherwise>
|
||||||
</h3>
|
<c:forEach items="${results.hits}" var="record" varStatus="i">
|
||||||
|
<p>${record.url}</p>
|
||||||
<p>
|
<p>${record.groupId}</p>
|
||||||
<my:showArtifactLink groupId="${record.groupId}" artifactId="${record.artifactId}"
|
<p>${record.artifactId}</p>
|
||||||
version="${record.version}" versions="${record.versions}"/>
|
</c:forEach>
|
||||||
|
<%--
|
||||||
<%-- TODO: hits
|
<c:forEach items="${results.hachcodeHits}" var="record" varStatus="i">
|
||||||
<table border="1px" width="100%" cellspacing="0">
|
<p>${record}</p>
|
||||||
<c:forEach items="${result.fieldMatchesEntrySet}" var="entry">
|
<h3 class="artifact-title">
|
||||||
<tr>
|
<my:showArtifactTitle groupId="${record.groupId}" artifactId="${record.artifactId}"
|
||||||
<td valign="top" width="15%" align="right"><c:out value="${entry.key}"/></td>
|
version="${record.version}"/>
|
||||||
<td valign="top">
|
</h3>
|
||||||
<c:forEach items="${entry.value}" var="item">
|
<p>
|
||||||
<c:out value="${item}" />
|
<my:showArtifactLink groupId="${record.groupId}" artifactId="${record.artifactId}"
|
||||||
</c:forEach>
|
version="${record.version}" versions="${record.versions}"/>
|
||||||
<br/>
|
</p>
|
||||||
</td>
|
</c:forEach>
|
||||||
</tr>
|
<c:forEach items="${results.bytecodeHits}" var="record" varStatus="i">
|
||||||
</c:forEach>
|
<p>${record}</p>
|
||||||
</table>
|
<h3 class="artifact-title">
|
||||||
</td>
|
<my:showArtifactTitle groupId="${record.groupId}" artifactId="${record.artifactId}"
|
||||||
<td>
|
version="${record.version}"/>
|
||||||
|
</h3>
|
||||||
<code>org.apache.maven</code>
|
<p>
|
||||||
(package)
|
<my:showArtifactLink groupId="${record.groupId}" artifactId="${record.artifactId}"
|
||||||
<br/>
|
version="${record.version}" versions="${record.versions}"/>
|
||||||
<code>org.apache.maven.model</code>
|
</p>
|
||||||
(package)
|
</c:forEach>
|
||||||
</td>
|
--%>
|
||||||
<td>
|
</c:otherwise>
|
||||||
<a href="artifact.html">Details</a>
|
</c:choose>
|
||||||
</td>
|
|
||||||
--%>
|
|
||||||
</p>
|
|
||||||
</c:forEach>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in New Issue