This project has retired. For details please refer to its Attic page.
DefaultIndexMerger xref
View Javadoc
1   package org.apache.archiva.indexer.maven.merger;
2   /*
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  
21  import org.apache.archiva.common.utils.FileUtils;
22  import org.apache.archiva.indexer.UnsupportedBaseContextException;
23  import org.apache.archiva.indexer.merger.IndexMerger;
24  import org.apache.archiva.indexer.merger.IndexMergerException;
25  import org.apache.archiva.indexer.merger.IndexMergerRequest;
26  import org.apache.archiva.indexer.merger.TemporaryGroupIndex;
27  import org.apache.archiva.repository.RepositoryRegistry;
28  import org.apache.archiva.repository.RepositoryType;
29  import org.apache.commons.lang.time.StopWatch;
30  import org.apache.maven.index.Indexer;
31  import org.apache.maven.index.context.ContextMemberProvider;
32  import org.apache.maven.index.context.IndexCreator;
33  import org.apache.maven.index.context.IndexingContext;
34  import org.apache.maven.index.context.StaticContextMemberProvider;
35  import org.apache.maven.index.packer.IndexPacker;
36  import org.apache.maven.index.packer.IndexPackingRequest;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  import org.springframework.scheduling.annotation.Async;
40  import org.springframework.stereotype.Service;
41  
42  import javax.inject.Inject;
43  import java.io.IOException;
44  import java.nio.file.Files;
45  import java.nio.file.Path;
46  import java.util.Collection;
47  import java.util.List;
48  import java.util.Objects;
49  import java.util.Optional;
50  import java.util.concurrent.CopyOnWriteArrayList;
51  import java.util.stream.Collectors;
52  
53  /**
54   * @author Olivier Lamy
55   * @since 1.4-M2
56   */
57  @Service("indexMerger#default")
58  public class DefaultIndexMerger
59      implements IndexMerger
60  {
61  
62      @Inject
63      RepositoryRegistry repositoryRegistry;
64  
65      private Logger log = LoggerFactory.getLogger( getClass() );
66  
67  
68      private final IndexPacker indexPacker;
69  
70      private Indexer indexer;
71  
72      private final List<IndexCreator> indexCreators;
73  
74      private List<TemporaryGroupIndex> temporaryGroupIndexes = new CopyOnWriteArrayList<>();
75  
76      private List<IndexingContext>  temporaryContextes = new CopyOnWriteArrayList<>(  );
77  
78      private List<String> runningGroups = new CopyOnWriteArrayList<>();
79  
80      @Inject
81      public DefaultIndexMerger( Indexer indexer, IndexPacker indexPacker, List<IndexCreator> indexCreators )
82      {
83          this.indexer = indexer;
84          this.indexPacker = indexPacker;
85          this.indexCreators = indexCreators;
86      }
87  
88      @Override
89      public IndexingContext buildMergedIndex( IndexMergerRequest indexMergerRequest )
90          throws IndexMergerException
91      {
92          String groupId = indexMergerRequest.getGroupId();
93  
94          if ( runningGroups.contains( groupId ) )
95          {
96              log.info( "skip build merge remote indexes for id: '{}' as already running", groupId );
97              return null;
98          }
99  
100         runningGroups.add( groupId );
101 
102         StopWatch stopWatch = new StopWatch();
103         stopWatch.reset();
104         stopWatch.start();
105 
106         Path mergedIndexDirectory = indexMergerRequest.getMergedIndexDirectory();
107 
108         String tempRepoId = mergedIndexDirectory.getFileName().toString();
109 
110         try
111         {
112             Path indexLocation = mergedIndexDirectory.resolve( indexMergerRequest.getMergedIndexPath() );
113 
114             List<IndexingContext> members = indexMergerRequest.getRepositoriesIds( ).stream( ).map( id ->
115                 repositoryRegistry.getRepository( id ) ).filter( repo -> repo.getType().equals( RepositoryType.MAVEN ) )
116                 .map( repo -> {
117                     try
118                     {
119                         return repo.getIndexingContext().getBaseContext( IndexingContext.class );
120                     }
121                     catch ( UnsupportedBaseContextException e )
122                     {
123                         return null;
124                         // Ignore
125                     }
126                 } ).filter( Objects::nonNull ).collect( Collectors.toList() );
127             ContextMemberProvider memberProvider = new StaticContextMemberProvider(members);
128             IndexingContext mergedCtx = indexer.createMergedIndexingContext( tempRepoId, tempRepoId, mergedIndexDirectory.toFile(),
129                 indexLocation.toFile(), true, memberProvider);
130             mergedCtx.optimize();
131 
132             if ( indexMergerRequest.isPackIndex() )
133             {
134                 IndexPackingRequest request = new IndexPackingRequest( mergedCtx, //
135                                                                        mergedCtx.acquireIndexSearcher().getIndexReader(), //
136                                                                        indexLocation.toFile() );
137                 indexPacker.packIndex( request );
138             }
139 
140             if ( indexMergerRequest.isTemporary() )
141             {
142                 temporaryGroupIndexes.add( new TemporaryGroupIndex( mergedIndexDirectory, tempRepoId, groupId,
143                                                                     indexMergerRequest.getMergedIndexTtl() ) );
144                 temporaryContextes.add(mergedCtx);
145             }
146             stopWatch.stop();
147             log.info( "merged index for repos {} in {} s", indexMergerRequest.getRepositoriesIds(),
148                       stopWatch.getTime() );
149             return mergedCtx;
150         }
151         catch ( IOException e)
152         {
153             throw new IndexMergerException( e.getMessage(), e );
154         }
155         finally
156         {
157             runningGroups.remove( groupId );
158         }
159     }
160 
161     @Async
162     @Override
163     public void cleanTemporaryGroupIndex( TemporaryGroupIndex temporaryGroupIndex )
164     {
165         if ( temporaryGroupIndex == null )
166         {
167             return;
168         }
169 
170         try
171         {
172 
173             Optional<IndexingContext> ctxOpt = temporaryContextes.stream( ).filter( ctx -> ctx.getId( ).equals( temporaryGroupIndex.getIndexId( ) ) ).findFirst( );
174             if (ctxOpt.isPresent()) {
175                 IndexingContext ctx = ctxOpt.get();
176                 indexer.closeIndexingContext( ctx, true );
177                 temporaryGroupIndexes.remove( temporaryGroupIndex );
178                 temporaryContextes.remove( ctx );
179                 Path directory = temporaryGroupIndex.getDirectory();
180                 if ( directory != null && Files.exists(directory) )
181                 {
182                     FileUtils.deleteDirectory( directory );
183                 }
184             }
185         }
186         catch ( IOException e )
187         {
188             log.warn( "fail to delete temporary group index {}", temporaryGroupIndex.getIndexId(), e );
189         }
190     }
191 
192     @Override
193     public Collection<TemporaryGroupIndex> getTemporaryGroupIndexes()
194     {
195         return this.temporaryGroupIndexes;
196     }
197 }