View Javadoc

1   package org.apache.maven.index;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0    
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Set;
27  
28  import org.apache.lucene.document.Document;
29  import org.apache.lucene.index.CorruptIndexException;
30  import org.apache.lucene.index.IndexReader;
31  import org.apache.lucene.index.Term;
32  import org.apache.lucene.search.TermQuery;
33  import org.apache.lucene.search.TopScoreDocCollector;
34  import org.apache.maven.index.context.IndexingContext;
35  import org.codehaus.plexus.logging.AbstractLogEnabled;
36  
37  /**
38   * A default scanning listener
39   * 
40   * @author Eugene Kuleshov
41   */
42  class DefaultScannerListener
43      extends AbstractLogEnabled
44      implements ArtifactScanningListener
45  {
46      private final IndexingContext context;
47  
48      private final IndexerEngine indexerEngine;
49  
50      private final boolean update;
51  
52      private final ArtifactScanningListener listener;
53  
54      private final Set<String> uinfos = new HashSet<String>();
55  
56      private final Set<String> processedUinfos = new HashSet<String>();
57  
58      private final Set<String> allGroups = new HashSet<String>();
59  
60      private final Set<String> groups = new HashSet<String>();
61  
62      private final List<Exception> exceptions = new ArrayList<Exception>();
63  
64      private int count = 0;
65  
66      DefaultScannerListener( IndexingContext context, //
67                              IndexerEngine indexerEngine, boolean update, //
68                              ArtifactScanningListener listener )
69      {
70          this.context = context;
71          this.indexerEngine = indexerEngine;
72          this.update = update;
73          this.listener = listener;
74      }
75  
76      public void scanningStarted( IndexingContext ctx )
77      {
78          try
79          {
80              if ( update )
81              {
82                  initialize( ctx );
83              }
84          }
85          catch ( IOException ex )
86          {
87              exceptions.add( ex );
88          }
89  
90          if ( listener != null )
91          {
92              listener.scanningStarted( ctx );
93          }
94      }
95  
96      public void artifactDiscovered( ArtifactContext ac )
97      {
98          String uinfo = ac.getArtifactInfo().getUinfo();
99  
100         // TODO: scattered across commented out changes while I was fixing NEXUS-2712, cstamas
101         // These changes should be applied by borks too much the fragile indexer
102 
103         // if ( VersionUtils.isSnapshot( ac.getArtifactInfo().version ) && processedUinfos.contains( uinfo ) )
104         if ( processedUinfos.contains( uinfo ) )
105         {
106             return; // skip individual snapshots
107         }
108 
109         boolean adding = processedUinfos.add( uinfo );
110 
111         if ( uinfos.contains( uinfo ) )
112         {
113             // already indexed
114             uinfos.remove( uinfo );
115             return;
116         }
117 
118         try
119         {
120             if ( listener != null )
121             {
122                 listener.artifactDiscovered( ac );
123             }
124 
125             if ( adding )
126             {
127                 indexerEngine.index( context, ac );
128             }
129             else
130             {
131                 indexerEngine.update( context, ac );
132             }
133 
134             for ( Exception e : ac.getErrors() )
135             {
136                 artifactError( ac, e );
137             }
138 
139             groups.add( ac.getArtifactInfo().getRootGroup() );
140             allGroups.add( ac.getArtifactInfo().groupId );
141 
142             count++;
143         }
144         catch ( IOException ex )
145         {
146             artifactError( ac, ex );
147         }
148     }
149 
150     public void scanningFinished( IndexingContext ctx, ScanningResult result )
151     {
152         result.setTotalFiles( count );
153 
154         for ( Exception ex : exceptions )
155         {
156             result.addException( ex );
157         }
158 
159         try
160         {
161             context.optimize();
162 
163             context.setRootGroups( groups );
164 
165             context.setAllGroups( allGroups );
166 
167             if ( update && !context.isReceivingUpdates() )
168             {
169                 removeDeletedArtifacts( context, result, result.getRequest().getStartingPath() );
170             }
171         }
172         catch ( IOException ex )
173         {
174             result.addException( ex );
175         }
176 
177         if ( listener != null )
178         {
179             listener.scanningFinished( ctx, result );
180         }
181 
182         if ( result.getDeletedFiles() > 0 || result.getTotalFiles() > 0 )
183         {
184             try
185             {
186                 context.updateTimestamp( true );
187 
188                 context.optimize();
189             }
190             catch ( Exception ex )
191             {
192                 result.addException( ex );
193             }
194         }
195     }
196 
197     public void artifactError( ArtifactContext ac, Exception e )
198     {
199         exceptions.add( e );
200 
201         if ( listener != null )
202         {
203             listener.artifactError( ac, e );
204         }
205     }
206 
207     private void initialize( IndexingContext ctx )
208         throws IOException, CorruptIndexException
209     {
210         IndexReader r = ctx.getIndexReader();
211 
212         for ( int i = 0; i < r.maxDoc(); i++ )
213         {
214             if ( !r.isDeleted( i ) )
215             {
216                 Document d = r.document( i );
217 
218                 String uinfo = d.get( ArtifactInfo.UINFO );
219 
220                 if ( uinfo != null )
221                 {
222                     uinfos.add( uinfo );
223 
224                     // add all existing groupIds to the lists, as they will
225                     // not be "discovered" and would be missing from the new list..
226                     String groupId = uinfo.substring( 0, uinfo.indexOf( '|' ) );
227                     int n = groupId.indexOf( '.' );
228                     groups.add( n == -1 ? groupId : groupId.substring( 0, n ) );
229                     allGroups.add( groupId );
230                 }
231             }
232         }
233     }
234 
235     private void removeDeletedArtifacts( IndexingContext context, ScanningResult result, String contextPath )
236         throws IOException
237     {
238         int deleted = 0;
239 
240         for ( String uinfo : uinfos )
241         {
242             TopScoreDocCollector collector = TopScoreDocCollector.create( 1, false );
243 
244             context.getIndexSearcher().search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), collector );
245 
246             if ( collector.getTotalHits() > 0 )
247             {
248                 String[] ra = ArtifactInfo.FS_PATTERN.split( uinfo );
249 
250                 ArtifactInfo ai = new ArtifactInfo();
251 
252                 ai.repository = context.getRepositoryId();
253 
254                 ai.groupId = ra[0];
255 
256                 ai.artifactId = ra[1];
257 
258                 ai.version = ra[2];
259 
260                 if ( ra.length > 3 )
261                 {
262                     ai.classifier = ArtifactInfo.renvl( ra[3] );
263                 }
264 
265                 if ( ra.length > 4 )
266                 {
267                     ai.packaging = ArtifactInfo.renvl( ra[4] );
268                 }
269 
270                 // minimal ArtifactContext for removal
271                 ArtifactContext ac = new ArtifactContext( null, null, null, ai, ai.calculateGav() );
272 
273                 for ( int i = 0; i < collector.getTotalHits(); i++ )
274                 {
275                     if ( contextPath == null
276                         || context.getGavCalculator().gavToPath( ac.getGav() ).startsWith( contextPath ) )
277                     {
278                         indexerEngine.remove( context, ac );
279                     }
280 
281                     deleted++;
282                 }
283             }
284         }
285 
286         if ( deleted > 0 )
287         {
288             context.commit();
289         }
290 
291         result.setDeletedFiles( deleted );
292     }
293 
294 }