This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.indexer.merger;
002/*
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020
021import org.apache.archiva.common.plexusbridge.MavenIndexerUtils;
022import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
023import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
024import org.apache.commons.io.FileUtils;
025import org.apache.commons.lang.time.StopWatch;
026import org.apache.maven.index.NexusIndexer;
027import org.apache.maven.index.context.IndexingContext;
028import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
029import org.apache.maven.index.packer.IndexPacker;
030import org.apache.maven.index.packer.IndexPackingRequest;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033import org.springframework.scheduling.annotation.Async;
034import org.springframework.stereotype.Service;
035
036import javax.inject.Inject;
037import java.io.File;
038import java.io.IOException;
039import java.util.Collection;
040import java.util.List;
041import java.util.concurrent.CopyOnWriteArrayList;
042
043/**
044 * @author Olivier Lamy
045 * @since 1.4-M2
046 */
047@Service("indexMerger#default")
048public class DefaultIndexMerger
049    implements IndexMerger
050{
051
052    private Logger log = LoggerFactory.getLogger( getClass() );
053
054    private MavenIndexerUtils mavenIndexerUtils;
055
056    private NexusIndexer indexer;
057
058    private IndexPacker indexPacker;
059
060    private List<TemporaryGroupIndex> temporaryGroupIndexes = new CopyOnWriteArrayList<>();
061
062    private List<String> runningGroups = new CopyOnWriteArrayList<String>();
063
064    @Inject
065    public DefaultIndexMerger( PlexusSisuBridge plexusSisuBridge, MavenIndexerUtils mavenIndexerUtils )
066        throws PlexusSisuBridgeException
067    {
068        this.indexer = plexusSisuBridge.lookup( NexusIndexer.class );
069        this.mavenIndexerUtils = mavenIndexerUtils;
070        indexPacker = plexusSisuBridge.lookup( IndexPacker.class, "default" );
071    }
072
073    @Override
074    public IndexingContext buildMergedIndex( IndexMergerRequest indexMergerRequest )
075        throws IndexMergerException
076    {
077        String groupId = indexMergerRequest.getGroupId();
078
079        if ( runningGroups.contains( groupId ) )
080        {
081            log.info( "skip build merge remote indexes for id: '{}' as already running", groupId );
082            return null;
083        }
084
085        runningGroups.add( groupId );
086
087        StopWatch stopWatch = new StopWatch();
088        stopWatch.reset();
089        stopWatch.start();
090
091        File mergedIndexDirectory = indexMergerRequest.getMergedIndexDirectory();
092
093        String tempRepoId = mergedIndexDirectory.getName();
094
095        try
096        {
097            File indexLocation = new File( mergedIndexDirectory, indexMergerRequest.getMergedIndexPath() );
098            IndexingContext indexingContext =
099                indexer.addIndexingContext( tempRepoId, tempRepoId, mergedIndexDirectory, indexLocation, null, null,
100                                            mavenIndexerUtils.getAllIndexCreators() );
101
102            for ( String repoId : indexMergerRequest.getRepositoriesIds() )
103            {
104                IndexingContext idxToMerge = indexer.getIndexingContexts().get( repoId );
105                if ( idxToMerge != null )
106                {
107                    indexingContext.merge( idxToMerge.getIndexDirectory() );
108                }
109            }
110
111            indexingContext.optimize();
112
113            if ( indexMergerRequest.isPackIndex() )
114            {
115                IndexPackingRequest request = new IndexPackingRequest( indexingContext, indexLocation );
116                indexPacker.packIndex( request );
117            }
118
119            if ( indexMergerRequest.isTemporary() )
120            {
121                temporaryGroupIndexes.add( new TemporaryGroupIndex( mergedIndexDirectory, tempRepoId, groupId,
122                                                                    indexMergerRequest.getMergedIndexTtl() ) );
123            }
124            stopWatch.stop();
125            log.info( "merged index for repos {} in {} s", indexMergerRequest.getRepositoriesIds(),
126                      stopWatch.getTime() );
127            return indexingContext;
128        }
129        catch ( IOException e )
130        {
131            throw new IndexMergerException( e.getMessage(), e );
132        }
133        catch ( UnsupportedExistingLuceneIndexException e )
134        {
135            throw new IndexMergerException( e.getMessage(), e );
136        }
137        finally
138        {
139            runningGroups.remove( groupId );
140        }
141    }
142
143    @Async
144    @Override
145    public void cleanTemporaryGroupIndex( TemporaryGroupIndex temporaryGroupIndex )
146    {
147        if ( temporaryGroupIndex == null )
148        {
149            return;
150        }
151
152        try
153        {
154            IndexingContext indexingContext = indexer.getIndexingContexts().get( temporaryGroupIndex.getIndexId() );
155            if ( indexingContext != null )
156            {
157                indexer.removeIndexingContext( indexingContext, true );
158            }
159            File directory = temporaryGroupIndex.getDirectory();
160            if ( directory != null && directory.exists() )
161            {
162                FileUtils.deleteDirectory( directory );
163            }
164            temporaryGroupIndexes.remove( temporaryGroupIndex );
165        }
166        catch ( IOException e )
167        {
168            log.warn( "fail to delete temporary group index {}", temporaryGroupIndex.getIndexId(), e );
169        }
170    }
171
172    @Override
173    public Collection<TemporaryGroupIndex> getTemporaryGroupIndexes()
174    {
175        return this.temporaryGroupIndexes;
176    }
177}