/** * 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.sonatype.nexus; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Date; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.maven.index.ArtifactInfo; import org.apache.maven.index.MAVEN; import org.apache.maven.index.NexusIndexer; import org.apache.maven.index.context.IndexingContext; import org.apache.maven.index.packer.IndexPacker; import org.apache.maven.index.packer.IndexPackingRequest; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.sonatype.jettytestsuite.ServletServer; import org.sonatype.nexus.index.DefaultIndexerManager; import org.sonatype.nexus.index.IndexerManager; import org.sonatype.nexus.proxy.maven.MavenProxyRepository; public class ReindexTest extends AbstractMavenRepoContentTests { public static final long A_DAY_MILLIS = 24 * 60 * 60 * 1000; private IndexerManager indexerManager; private ServletServer servletServer; private NexusIndexer nexusIndexer; private IndexPacker indexPacker; @Override protected void setUp() throws Exception { super.setUp(); indexerManager = lookup( IndexerManager.class ); nexusIndexer = lookup( NexusIndexer.class ); indexPacker = lookup( IndexPacker.class ); servletServer = lookup( ServletServer.class ); servletServer.start(); } @Override protected void tearDown() throws Exception { servletServer.stop(); super.tearDown(); } protected void makeCentralPointTo( String url ) throws Exception { MavenProxyRepository central = repositoryRegistry.getRepositoryWithFacet( "central", MavenProxyRepository.class ); // redirect it to our "sppof" jetty (see ReindexTest.xml in src/test/resources.... central.setRemoteUrl( url ); // make the central download the remote indexes is found central.setDownloadRemoteIndexes( true ); nexusConfiguration.saveConfiguration(); waitForTasksToStop(); } protected File getIndexFamilyDirectory( String path ) { File indexDirectory = new File( new File( getBasedir() ), "target/indexFamily/" + path ); return indexDirectory; } protected File getRemoteRepositoryRoot( String path ) { // Be aware, that "name" != "repoId"! For example, "central-inc1", "central-inc2"... are all "slices" of // "central" repo in different time! File root = new File( new File( getBasedir() ), "target/test-classes/reposes-remote/" + path ); return root; } protected void shiftContextInTime( IndexingContext ctx, int shiftDays ) throws IOException { if ( shiftDays != 0 ) { IndexWriter iw = ctx.getIndexWriter(); for ( int docNum = 0; docNum < ctx.getIndexReader().maxDoc(); docNum++ ) { if ( !ctx.getIndexReader().isDeleted( docNum ) ) { Document doc = ctx.getIndexReader().document( docNum ); String lastModified = doc.get( ArtifactInfo.LAST_MODIFIED ); if ( lastModified != null ) { long lm = Long.parseLong( lastModified ); lm = lm + ( shiftDays * A_DAY_MILLIS ); doc.removeFields( ArtifactInfo.LAST_MODIFIED ); doc.add( new Field( ArtifactInfo.LAST_MODIFIED, Long.toString( lm ), Field.Store.YES, Field.Index.NO ) ); iw.updateDocument( new Term( ArtifactInfo.UINFO, doc.get( ArtifactInfo.UINFO ) ), doc ); } } } ctx.optimize(); ctx.commit(); // shift timestamp too if ( ctx.getTimestamp() != null ) { ctx.updateTimestamp( true, new Date( ctx.getTimestamp().getTime() + ( shiftDays * A_DAY_MILLIS ) ) ); } else { ctx.updateTimestamp( true, new Date( System.currentTimeMillis() + ( shiftDays * A_DAY_MILLIS ) ) ); } } } /** * Will reindex, shift if needed and publish indexes for a "remote" repository (published over jetty component). * * @param repositoryRoot * @param repositoryId * @param deleteIndexFiles * @param shiftDays * @throws IOException */ protected void reindexRemoteRepositoryAndPublish( File repositoryRoot, String repositoryId, boolean deleteIndexFiles, int shiftDays ) throws IOException, ComponentLookupException { File indexDirectory = getIndexFamilyDirectory( repositoryId ); Directory directory = FSDirectory.open( indexDirectory ); IndexingContext ctx = nexusIndexer.addIndexingContextForced( repositoryId + "-temp", repositoryId, repositoryRoot, directory, null, null, new IndexCreatorHelper( getContainer() ).getFullCreators() ); // shifting if needed (very crude way to do it, but heh) shiftContextInTime( ctx, shiftDays ); // and scan "today" nexusIndexer.scan( ctx ); ctx.updateTimestamp( true ); // pack it up File targetDir = new File( repositoryRoot, ".index" ); targetDir.mkdirs(); IndexPackingRequest ipr = new IndexPackingRequest( ctx, targetDir ); ipr.setCreateIncrementalChunks( true ); indexPacker.packIndex( ipr ); nexusIndexer.removeIndexingContext( ctx, deleteIndexFiles ); } protected void validateIndexWithIdentify( boolean shouldBePresent, String sha1Hash, String gid, String aid, String version ) throws Exception { Collection<ArtifactInfo> ais = indexerManager.identifyArtifact( MAVEN.SHA1, sha1Hash ); if ( shouldBePresent ) { assertTrue( "Should find " + gid + ":" + aid + ":" + version, ais.size() > 0 ); ArtifactInfo ai = ais.iterator().next(); assertEquals( gid, ai.groupId ); assertEquals( aid, ai.artifactId ); assertEquals( version, ai.version ); } else { assertEquals( "Should not find " + gid + ":" + aid + ":" + version, 0, ais.size() ); } } public void testHostedRepositoryReindex() throws Exception { fillInRepo(); indexerManager.reindexRepository( null, "releases", true ); validateIndexWithIdentify( true, "86e12071021fa0be4ec809d4d2e08f07b80d4877", "org.sonatype.nexus", "nexus-indexer", "1.0-beta-4" ); } public void testProxyRepositoryReindex() throws Exception { fillInRepo(); reindexRemoteRepositoryAndPublish( getRemoteRepositoryRoot( "central" ), "central", true, 0 ); makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central/" ); indexerManager.reindexRepository( null, "central", true ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); } public void testGroupReindex() throws Exception { fillInRepo(); reindexRemoteRepositoryAndPublish( getRemoteRepositoryRoot( "central" ), "central", true, 0 ); makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central/" ); // central is member of public group indexerManager.reindexRepository( null, "public", true ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); } public void testCurrentIncrementalIndexes() throws Exception { // day 1 reindexRemoteRepositoryAndPublish( getRemoteRepositoryRoot( "central-inc1" ), "central", false, 0 ); makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc1/" ); indexerManager.reindexRepository( null, "central", true ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( false, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( false, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( false, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); // day 2 (1 day passed), so shift both ctxes "in time" reindexRemoteRepositoryAndPublish( getRemoteRepositoryRoot( "central-inc2" ), "central", false, -1 ); shiftContextInTime( ( (DefaultIndexerManager) indexerManager ).getRepositoryIndexContext( "central" ), -1 ); makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc2/" ); indexerManager.reindexRepository( null, "central", false ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( true, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( false, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); // day 3 reindexRemoteRepositoryAndPublish( getRemoteRepositoryRoot( "central-inc3" ), "central", false, -1 ); shiftContextInTime( ( (DefaultIndexerManager) indexerManager ).getRepositoryIndexContext( "central" ), -1 ); makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc3/" ); indexerManager.reindexRepository( null, "central", false ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( true, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( true, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); } public void testV1IncrementalIndexes() throws Exception { // day 1 makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc1-v1/" ); indexerManager.reindexRepository( null, "central", true ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( false, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( false, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( false, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); // day 2 makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc2-v1/" ); indexerManager.reindexRepository( null, "central", false ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( true, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( false, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); // day 3 makeCentralPointTo( "http://localhost:" + super.getContainer().getContext().get( PROXY_SERVER_PORT ) + "/central-inc3-v1/" ); indexerManager.reindexRepository( null, "central", false ); // validation validateIndexWithIdentify( true, "cf4f67dae5df4f9932ae7810f4548ef3e14dd35e", "antlr", "antlr", "2.7.6" ); validateIndexWithIdentify( true, "83cd2cd674a217ade95a4bb83a8a14f351f48bd0", "antlr", "antlr", "2.7.7" ); validateIndexWithIdentify( true, "3640dd71069d7986c9a14d333519216f4ca5c094", "log4j", "log4j", "1.2.8" ); validateIndexWithIdentify( true, "057b8740427ee6d7b0b60792751356cad17dc0d9", "log4j", "log4j", "1.2.12" ); validateIndexWithIdentify( true, "f0a0d2e29ed910808c33135a3a5a51bba6358f7b", "log4j", "log4j", "1.2.15" ); } }