/** * Copyright (c) 2008-2011 Sonatype, Inc. * All rights reserved. Includes the third-party code listed at http://www.sonatype.com/products/nexus/attributions. * * This program is free software: you can redistribute it and/or modify it only under the terms of the GNU Affero General * Public License Version 3 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License Version 3 * for more details. * * You should have received a copy of the GNU Affero General Public License Version 3 along with this program. If not, see * http://www.gnu.org/licenses. * * Sonatype Nexus (TM) Open Source Version is available from Sonatype, Inc. Sonatype and Sonatype Nexus are trademarks of * Sonatype, Inc. Apache Maven is a trademark of the Apache Foundation. M2Eclipse is a trademark of the Eclipse Foundation. * All other trademarks are the property of their respective owners. */ package org.damian; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.lucene.search.Query; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Configuration; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.sonatype.nexus.index.ArtifactInfo; import org.sonatype.nexus.index.ArtifactInfoGroup; import org.sonatype.nexus.index.FlatSearchRequest; import org.sonatype.nexus.index.FlatSearchResponse; import org.sonatype.nexus.index.GroupedSearchRequest; import org.sonatype.nexus.index.GroupedSearchResponse; import org.sonatype.nexus.index.Grouping; import org.sonatype.nexus.index.NexusIndexer; import org.sonatype.nexus.index.context.IndexCreator; import org.sonatype.nexus.index.context.IndexingContext; import org.sonatype.nexus.index.context.UnsupportedExistingLuceneIndexException; import org.sonatype.nexus.index.packer.IndexPacker; import org.sonatype.nexus.index.packer.IndexPackingRequest; import org.sonatype.nexus.index.search.grouping.GAVGrouping; import org.sonatype.nexus.index.updater.IndexUpdateRequest; import org.sonatype.nexus.index.updater.IndexUpdater; /** * Sample app to show how to integrate with the nexus indexer. Note that this is a simple plexus * component extending the SampleApp interface * * public interface SampleApp * { * void index() * throws IOException; * * Set<ArtifactInfo> searchIndexFlat( String field, String value ) * throws IOException; * * Set<ArtifactInfo> searchIndexFlat( Query query ) * throws IOException; * * Map<String, ArtifactInfoGroup> searchIndexGrouped( String field, String value ) * throws IOException; * * Map<String, ArtifactInfoGroup> searchIndexGrouped( String field, String value, Grouping grouping ) * throws IOException; * * Map<String, ArtifactInfoGroup> searchIndexGrouped( Query q, Grouping grouping ) * throws IOException; * * void publishIndex( File targetDirectory ) * throws IOException; * * void updateRemoteIndex() * throws IOException; * } * * @author Damian * */ @Component( role = SampleApp.class ) public class DefaultSampleApp implements SampleApp, Initializable, Disposable { // The nexus indexer @Requirement private NexusIndexer indexer; // The nexus index packer @Requirement private IndexPacker indexPacker; // The nexus index updater @Requirement private IndexUpdater indexUpdater; // The list of index creators we will be using (all of them) @Requirement( role = IndexCreator.class ) private List<IndexCreator> indexCreators; // The indexing context private IndexingContext context = null; // The path to the repository to index, value will be pulled from // the plexus context @Configuration( value = "${repository.path}" ) private File repositoryDirectoryPath; // The path to store index files, value will be pulled from // the plexus context @Configuration( value = "${index.path}") private File indexDirectoryPath; // Initialize the index context public void initialize() throws InitializationException { try { // Add the indexing context context = indexer.addIndexingContext( // id of the context "sample", // id of the repository "sampleRepo", // directory containing repository repositoryDirectoryPath, // directory where index will be stored indexDirectoryPath, // remote repository url...not in this example null, // index update url...not in this example null, // list of index creators indexCreators ); } catch ( UnsupportedExistingLuceneIndexException e ) { throw new InitializationException( "Error initializing IndexingContext", e ); } catch ( IOException e ) { throw new InitializationException( "Error initializing IndexingContext", e ); } } // clean up the context public void dispose() { if ( context != null ) { // Remove the index files, typically would not want to remove the index files, so // would pass in false, but this is just a test app... try { indexer.removeIndexingContext( context, true ); } catch ( IOException e ) { e.printStackTrace(); } } } // index the repository public void index() throws IOException { // Perform the scan, which will index all artifacts in the repository directory // once this is done, searching will be available indexer.scan( context ); } // search for artifacts public Set<ArtifactInfo> searchIndexFlat( String field, String value ) throws IOException { // Build a query that will search the documents for the field set to the supplied value // This uses predefined logic to define the query // See http://svn.sonatype.org/nexus/trunk/nexus-indexer/src/main/java/org/sonatype/nexus/index/DefaultQueryCreator.java // for details Query query = indexer.constructQuery( field, value ); return searchIndexFlat( query ); } // search for artifacts using pre-built query public Set<ArtifactInfo> searchIndexFlat( Query query ) throws IOException { // Build the request FlatSearchRequest request = new FlatSearchRequest( query ); // Perform the search FlatSearchResponse response = indexer.searchFlat( request ); // Return the artifact info objects return response.getResults(); } public Map<String, ArtifactInfoGroup> searchIndexGrouped( String field, String value ) throws IOException { // We will simply use the GAV grouping, meaning that each groupId/artifactId/version/classifier // will have its own entry in the returned map return searchIndexGrouped( field, value, new GAVGrouping() ); } public Map<String, ArtifactInfoGroup> searchIndexGrouped( String field, String value, Grouping grouping ) throws IOException { // Build a query that will search the documents for the field set to the supplied value // This uses predefined logic to define the query // See http://svn.sonatype.org/nexus/trunk/nexus-indexer/src/main/java/org/sonatype/nexus/index/DefaultQueryCreator.java // for details Query query = indexer.constructQuery( field, value ); return searchIndexGrouped( query, grouping ); } public Map<String, ArtifactInfoGroup> searchIndexGrouped( Query q, Grouping grouping ) throws IOException { GroupedSearchRequest request = new GroupedSearchRequest( q, grouping ); GroupedSearchResponse response = indexer.searchGrouped( request ); return response.getResults(); } public void publishIndex( File targetDirectory ) throws IOException { IndexPackingRequest packReq = new IndexPackingRequest( context, targetDirectory ); packReq.setCreateChecksumFiles( true ); packReq.setCreateIncrementalChunks( true ); //NOTE: There are numerous other options you can set in the index pack request indexPacker.packIndex( packReq ); } public void updateRemoteIndex() throws IOException { IndexUpdateRequest updRequest = new IndexUpdateRequest( context ); //not too much to configure with the IndexUpdateRequest, but you can //supply your own ResourceFetcher if you would like to use some other //means to retrieve the index file than the default. You can also //add auth and proxy info to default ResourceFetcher, and you can set //a transfer listener to be notified of transfer events. //But by default, will simply use the remote index url assigned to the index //context to retrieve new index file, and merge locally //also you can force full update, which will wipe out what is local, and replace //with the latest remote content. indexUpdater.fetchAndUpdateIndex( updRequest ); } }