Repository: maven-indexer Updated Branches: refs/heads/master fb50105a0 -> a11321c49
Adding Tamas' examples ([email protected]:cstamas/maven-indexer-examples.git) as a separate module. Project: http://git-wip-us.apache.org/repos/asf/maven-indexer/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-indexer/commit/d58f1dd0 Tree: http://git-wip-us.apache.org/repos/asf/maven-indexer/tree/d58f1dd0 Diff: http://git-wip-us.apache.org/repos/asf/maven-indexer/diff/d58f1dd0 Branch: refs/heads/master Commit: d58f1dd064db3d3172e3d22ee9035a21bb1315bd Parents: fb50105 Author: Martin Todorov <[email protected]> Authored: Sun Jun 29 19:31:19 2014 +0100 Committer: Martin Todorov <[email protected]> Committed: Sun Jun 29 19:31:19 2014 +0100 ---------------------------------------------------------------------- indexer-examples/README.md | 18 + indexer-examples/pom.xml | 88 +++++ .../indexer/example/BasicUsageExample.java | 355 +++++++++++++++++++ .../indexer/example/BasicUsageExampleTest.java | 35 ++ 4 files changed, 496 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/d58f1dd0/indexer-examples/README.md ---------------------------------------------------------------------- diff --git a/indexer-examples/README.md b/indexer-examples/README.md new file mode 100644 index 0000000..477d38b --- /dev/null +++ b/indexer-examples/README.md @@ -0,0 +1,18 @@ +Maven Indexer Example 01 +====== + +This example covers simple use cases and is runnable as Java App or just using Maven "test" goal (as there is a Junit test simply executing the main() method, to not have to fuss with classpath etc.) + +Try following steps: + +``` +$ cd indexer-example-01 +$ mvn clean test + ... first run will take few minutes to download the index, and then will run showing some output +$ mvn test + ... (no clean goal!) second run will finish quickly, as target folder will already contain an up-to-date index +``` + + +Have fun, +~t~ \ No newline at end of file http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/d58f1dd0/indexer-examples/pom.xml ---------------------------------------------------------------------- diff --git a/indexer-examples/pom.xml b/indexer-examples/pom.xml new file mode 100644 index 0000000..5691e95 --- /dev/null +++ b/indexer-examples/pom.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.maven.indexer</groupId> + <artifactId>maven-indexer</artifactId> + <version>6.0-SNAPSHOT</version> + </parent> + + <artifactId>indexer-examples</artifactId> + + <name>Maven :: Indexer Examples</name> + <description> + This module contains Maven Indexer usage examples. + </description> + + <!-- IMPORTANT! * WHEN YOU CHANGE DEPS MAKE SURE TO UPDATE SHADE CONFIG! * DON'T FORGET OTHERWISE YOU ARE RENDERING CLI + UNWORKABLE! --> + + <dependencies> + <!-- For search app in general --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.5</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.indexer</groupId> + <artifactId>indexer-core</artifactId> + <version>6.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + <!-- For ResourceFetcher implementation, if used --> + <dependency> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-http-lightweight</artifactId> + <version>2.3</version> + <scope>compile</scope> + </dependency> + + <!-- Runtime: DI, but using Plexus Shim as we use Wagon --> + <dependency> + <groupId>org.eclipse.sisu</groupId> + <artifactId>org.eclipse.sisu.plexus</artifactId> + <version>0.2.1</version> + </dependency> + <dependency> + <groupId>org.sonatype.sisu</groupId> + <artifactId>sisu-guice</artifactId> + <version>3.2.2</version> + </dependency> + + <!-- Test --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.7.5</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/d58f1dd0/indexer-examples/src/main/java/org/apache/maven/indexer/example/BasicUsageExample.java ---------------------------------------------------------------------- diff --git a/indexer-examples/src/main/java/org/apache/maven/indexer/example/BasicUsageExample.java b/indexer-examples/src/main/java/org/apache/maven/indexer/example/BasicUsageExample.java new file mode 100644 index 0000000..1de6831 --- /dev/null +++ b/indexer-examples/src/main/java/org/apache/maven/indexer/example/BasicUsageExample.java @@ -0,0 +1,355 @@ +package org.apache.maven.indexer.example; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.apache.lucene.document.Document; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.MultiFields; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.util.Bits; +import org.apache.maven.index.ArtifactInfo; +import org.apache.maven.index.ArtifactInfoFilter; +import org.apache.maven.index.ArtifactInfoGroup; +import org.apache.maven.index.Field; +import org.apache.maven.index.FlatSearchRequest; +import org.apache.maven.index.FlatSearchResponse; +import org.apache.maven.index.GroupedSearchRequest; +import org.apache.maven.index.GroupedSearchResponse; +import org.apache.maven.index.Grouping; +import org.apache.maven.index.Indexer; +import org.apache.maven.index.IteratorSearchRequest; +import org.apache.maven.index.IteratorSearchResponse; +import org.apache.maven.index.MAVEN; +import org.apache.maven.index.context.IndexCreator; +import org.apache.maven.index.context.IndexUtils; +import org.apache.maven.index.context.IndexingContext; +import org.apache.maven.index.expr.SourcedSearchExpression; +import org.apache.maven.index.expr.UserInputSearchExpression; +import org.apache.maven.index.search.grouping.GAGrouping; +import org.apache.maven.index.updater.IndexUpdateRequest; +import org.apache.maven.index.updater.IndexUpdateResult; +import org.apache.maven.index.updater.IndexUpdater; +import org.apache.maven.index.updater.ResourceFetcher; +import org.apache.maven.index.updater.WagonHelper; +import org.apache.maven.wagon.Wagon; +import org.apache.maven.wagon.events.TransferEvent; +import org.apache.maven.wagon.events.TransferListener; +import org.apache.maven.wagon.observers.AbstractTransferListener; +import org.codehaus.plexus.DefaultPlexusContainer; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.PlexusContainerException; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.aether.util.version.GenericVersionScheme; +import org.eclipse.aether.version.InvalidVersionSpecificationException; +import org.eclipse.aether.version.Version; + +/** + * Hello world! + */ +public class BasicUsageExample +{ + public static void main( String[] args ) + throws Exception + { + final BasicUsageExample basicUsageExample = new BasicUsageExample(); + basicUsageExample.perform(); + } + + // == + + private final PlexusContainer plexusContainer; + + private final Indexer indexer; + + private final IndexUpdater indexUpdater; + + private final Wagon httpWagon; + + private IndexingContext centralContext; + + public BasicUsageExample() + throws PlexusContainerException, ComponentLookupException + { + // here we create Plexus container, the Maven default IoC container + // Plexus falls outside of MI scope, just accept the fact that + // MI is a Plexus component ;) + // If needed more info, ask on Maven Users list or Plexus Users list + // google is your friend! + this.plexusContainer = new DefaultPlexusContainer(); + + // lookup the indexer components from plexus + this.indexer = plexusContainer.lookup( Indexer.class ); + this.indexUpdater = plexusContainer.lookup( IndexUpdater.class ); + // lookup wagon used to remotely fetch index + this.httpWagon = plexusContainer.lookup( Wagon.class, "http" ); + + } + + public void perform() + throws IOException, ComponentLookupException, InvalidVersionSpecificationException + { + // Files where local cache is (if any) and Lucene Index should be located + File centralLocalCache = new File( "target/central-cache" ); + File centralIndexDir = new File( "target/central-index" ); + + // Creators we want to use (search for fields it defines) + List<IndexCreator> indexers = new ArrayList<IndexCreator>(); + indexers.add( plexusContainer.lookup( IndexCreator.class, "min" ) ); + indexers.add( plexusContainer.lookup( IndexCreator.class, "jarContent" ) ); + indexers.add( plexusContainer.lookup( IndexCreator.class, "maven-plugin" ) ); + + // Create context for central repository index + centralContext = + indexer.createIndexingContext( "central-context", "central", centralLocalCache, centralIndexDir, + "http://repo1.maven.org/maven2", null, true, true, indexers ); + + // Update the index (incremental update will happen if this is not 1st run and files are not deleted) + // This whole block below should not be executed on every app start, but rather controlled by some configuration + // since this block will always emit at least one HTTP GET. Central indexes are updated once a week, but + // other index sources might have different index publishing frequency. + // Preferred frequency is once a week. + if ( true ) + { + System.out.println( "Updating Index..." ); + System.out.println( "This might take a while on first run, so please be patient!" ); + // Create ResourceFetcher implementation to be used with IndexUpdateRequest + // Here, we use Wagon based one as shorthand, but all we need is a ResourceFetcher implementation + TransferListener listener = new AbstractTransferListener() + { + public void transferStarted( TransferEvent transferEvent ) + { + System.out.print( " Downloading " + transferEvent.getResource().getName() ); + } + + public void transferProgress( TransferEvent transferEvent, byte[] buffer, int length ) + { + } + + public void transferCompleted( TransferEvent transferEvent ) + { + System.out.println( " - Done" ); + } + }; + ResourceFetcher resourceFetcher = new WagonHelper.WagonFetcher( httpWagon, listener, null, null ); + + Date centralContextCurrentTimestamp = centralContext.getTimestamp(); + IndexUpdateRequest updateRequest = new IndexUpdateRequest( centralContext, resourceFetcher ); + IndexUpdateResult updateResult = indexUpdater.fetchAndUpdateIndex( updateRequest ); + if ( updateResult.isFullUpdate() ) + { + System.out.println( "Full update happened!" ); + } + else if ( updateResult.getTimestamp().equals( centralContextCurrentTimestamp ) ) + { + System.out.println( "No update needed, index is up to date!" ); + } + else + { + System.out.println( "Incremental update happened, change covered " + centralContextCurrentTimestamp + + " - " + updateResult.getTimestamp() + " period." ); + } + + System.out.println(); + } + + System.out.println(); + System.out.println( "Using index" ); + System.out.println( "===========" ); + System.out.println(); + + // ==== + // Case: + // dump all the GAVs + // NOTE: will not actually execute do this below, is too long to do (Central is HUGE), but is here as code + // example + if ( false ) + { + final IndexSearcher searcher = centralContext.acquireIndexSearcher(); + try + { + final IndexReader ir = searcher.getIndexReader(); + Bits liveDocs = MultiFields.getLiveDocs(ir); + for ( int i = 0; i < ir.maxDoc(); i++ ) + { + if ( liveDocs == null || liveDocs.get( i ) ) + { + final Document doc = ir.document( i ); + final ArtifactInfo ai = IndexUtils.constructArtifactInfo( doc, centralContext ); + System.out.println( ai.getGroupId() + ":" + ai.getArtifactId() + ":" + ai.getVersion() + ":" + ai.getClassifier() + + " (sha1=" + ai.getSha1() + ")" ); + } + } + } + finally + { + centralContext.releaseIndexSearcher( searcher ); + } + } + + // ==== + // Case: + // Search for all GAVs with known G and A and having version greater than V + + final GenericVersionScheme versionScheme = new GenericVersionScheme(); + final String versionString = "1.5.0"; + final Version version = versionScheme.parseVersion( versionString ); + + // construct the query for known GA + final Query groupIdQ = + indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( "org.sonatype.nexus" ) ); + final Query artifactIdQ = + indexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( "nexus-api" ) ); + final BooleanQuery query = new BooleanQuery(); + query.add( groupIdQ, Occur.MUST ); + query.add( artifactIdQ, Occur.MUST ); + + // we want "jar" artifacts only + query.add( indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "jar" ) ), Occur.MUST ); + // we want main artifacts only (no classifier) + // Note: this below is unfinished API, needs fixing + query.add( indexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( Field.NOT_PRESENT ) ), + Occur.MUST_NOT ); + + // construct the filter to express "V greater than" + final ArtifactInfoFilter versionFilter = new ArtifactInfoFilter() + { + public boolean accepts( final IndexingContext ctx, final ArtifactInfo ai ) + { + try + { + final Version aiV = versionScheme.parseVersion( ai.getVersion() ); + // Use ">=" if you are INCLUSIVE + return aiV.compareTo( version ) > 0; + } + catch ( InvalidVersionSpecificationException e ) + { + // do something here? be safe and include? + return true; + } + } + }; + + System.out.println( "Searching for all GAVs with G=org.sonatype.nexus and nexus-api and having V greater than 1.5.0" ); + final IteratorSearchRequest request = + new IteratorSearchRequest( query, Collections.singletonList( centralContext ), versionFilter ); + final IteratorSearchResponse response = indexer.searchIterator( request ); + for ( ArtifactInfo ai : response ) + { + System.out.println( ai.toString() ); + } + + // Case: + // Use index + // Searching for some artifact + Query gidQ = indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( "org.apache.maven.indexer" ) ); + Query aidQ = indexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( "indexer-artifact" ) ); + + BooleanQuery bq = new BooleanQuery(); + bq.add( gidQ, Occur.MUST ); + bq.add( aidQ, Occur.MUST ); + + searchAndDump( indexer, "all artifacts under GA org.apache.maven.indexer:indexer-artifact", bq ); + + // Searching for some main artifact + bq = new BooleanQuery(); + bq.add( gidQ, Occur.MUST ); + bq.add( aidQ, Occur.MUST ); + // bq.add( nexusIndexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( "*" ) ), Occur.MUST_NOT + // ); + + searchAndDump( indexer, "main artifacts under GA org.apache.maven.indexer:indexer-artifact", bq ); + + // doing sha1 search + searchAndDump( indexer, "SHA1 7ab67e6b20e5332a7fb4fdf2f019aec4275846c2", indexer.constructQuery( MAVEN.SHA1, + new SourcedSearchExpression( "7ab67e6b20e5332a7fb4fdf2f019aec4275846c2" ) ) ); + + searchAndDump( indexer, "SHA1 7ab67e6b20 (partial hash)", + indexer.constructQuery( MAVEN.SHA1, new UserInputSearchExpression( "7ab67e6b20" ) ) ); + + // doing classname search (incomplete classname) + searchAndDump( indexer, "classname DefaultNexusIndexer (note: Central does not publish classes in the index)", + indexer.constructQuery( MAVEN.CLASSNAMES, new UserInputSearchExpression( "DefaultNexusIndexer" ) ) ); + + // doing search for all "canonical" maven plugins latest versions + bq = new BooleanQuery(); + bq.add( indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "maven-plugin" ) ), Occur.MUST ); + bq.add( indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( "org.apache.maven.plugins" ) ), + Occur.MUST ); + searchGroupedAndDump( indexer, "all \"canonical\" maven plugins", bq, new GAGrouping() ); + + // doing search for all archetypes latest versions + searchGroupedAndDump( indexer, "all maven archetypes (latest versions)", + indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "maven-archetype" ) ), new GAGrouping() ); + + // close cleanly + indexer.closeIndexingContext( centralContext, false ); + } + + public void searchAndDump( Indexer nexusIndexer, String descr, Query q ) + throws IOException + { + System.out.println( "Searching for " + descr ); + + FlatSearchResponse response = nexusIndexer.searchFlat( new FlatSearchRequest( q, centralContext ) ); + + for ( ArtifactInfo ai : response.getResults() ) + { + System.out.println( ai.toString() ); + } + + System.out.println( "------" ); + System.out.println( "Total: " + response.getTotalHitsCount() ); + System.out.println(); + } + + public void searchGroupedAndDump( Indexer nexusIndexer, String descr, Query q, Grouping g ) + throws IOException + { + System.out.println( "Searching for " + descr ); + + GroupedSearchResponse response = nexusIndexer.searchGrouped( new GroupedSearchRequest( q, g, centralContext ) ); + + for ( Map.Entry<String, ArtifactInfoGroup> entry : response.getResults().entrySet() ) + { + ArtifactInfo ai = entry.getValue().getArtifactInfos().iterator().next(); + System.out.println( "* Entry " + ai ); + System.out.println( " Latest version: " + ai.getVersion() ); + System.out.println( StringUtils.isBlank( ai.getDescription() ) ? "No description in plugin's POM." + : StringUtils.abbreviate( ai.getDescription(), 60 ) ); + System.out.println(); + } + + System.out.println( "------" ); + System.out.println( "Total record hits: " + response.getTotalHitsCount() ); + System.out.println(); + } +} http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/d58f1dd0/indexer-examples/src/test/java/org/apache/maven/indexer/example/BasicUsageExampleTest.java ---------------------------------------------------------------------- diff --git a/indexer-examples/src/test/java/org/apache/maven/indexer/example/BasicUsageExampleTest.java b/indexer-examples/src/test/java/org/apache/maven/indexer/example/BasicUsageExampleTest.java new file mode 100644 index 0000000..e32ade1 --- /dev/null +++ b/indexer-examples/src/test/java/org/apache/maven/indexer/example/BasicUsageExampleTest.java @@ -0,0 +1,35 @@ +package org.apache.maven.indexer.example; + +/* + * 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.TestCase; + +/** + * Unit test for simple App. + */ +public class BasicUsageExampleTest + extends TestCase +{ + public void testApp() + throws Exception + { + BasicUsageExample.main( null ); + } +}
