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 javax.inject.Inject;
23  import javax.inject.Named;
24  import javax.inject.Singleton;
25  import java.io.File;
26  import java.util.Arrays;
27  import java.util.Comparator;
28  import java.util.Set;
29  import java.util.TreeSet;
30  
31  import org.apache.maven.index.context.IndexingContext;
32  
33  /**
34   * A default repository scanner for Maven 2 repository.
35   * 
36   * @author Jason Van Zyl
37   * @author Tamas Cservenak
38   */
39  @Singleton
40  @Named
41  public class DefaultScanner
42      implements Scanner
43  {
44  
45      private final ArtifactContextProducer artifactContextProducer;
46  
47  
48      @Inject
49      public DefaultScanner( ArtifactContextProducer artifactContextProducer )
50      {
51          this.artifactContextProducer = artifactContextProducer;
52      }
53  
54      public ScanningResult scan( ScanningRequest request )
55      {
56          request.getArtifactScanningListener().scanningStarted( request.getIndexingContext() );
57  
58          ScanningResult result = new ScanningResult( request );
59  
60          scanDirectory( request.getStartingDirectory(), request );
61  
62          request.getArtifactScanningListener().scanningFinished( request.getIndexingContext(), result );
63  
64          return result;
65      }
66  
67      private void scanDirectory( File dir, ScanningRequest request )
68      {
69          if ( dir == null )
70          {
71              return;
72          }
73  
74          File[] fileArray = dir.listFiles();
75  
76          if ( fileArray != null )
77          {
78              Set<File> files = new TreeSet<File>( new ScannerFileComparator() );
79  
80              files.addAll( Arrays.asList( fileArray ) );
81  
82              for ( File f : files )
83              {
84                  if ( f.getName().startsWith( "." ) )
85                  {
86                      continue; // skip all hidden files and directories
87                  }
88  
89                  if ( f.isDirectory() )
90                  {
91                      scanDirectory( f, request );
92                  }
93                  // else if ( !AbstractIndexCreator.isIndexable( f ) )
94                  // {
95                  // continue; // skip non-indexable files
96                  // }
97                  else
98                  {
99                      processFile( f, request );
100                 }
101             }
102         }
103     }
104 
105     private void processFile( File file, ScanningRequest request )
106     {
107         IndexingContext context = request.getIndexingContext();
108 
109         ArtifactContext ac = artifactContextProducer.getArtifactContext( context, file );
110 
111         if ( ac != null )
112         {
113             request.getArtifactScanningListener().artifactDiscovered( ac );
114         }
115     }
116 
117     // ==
118 
119     /**
120      * A special comparator to overcome some very bad limitations of nexus-indexer during scanning: using this
121      * comparator, we force to "discover" POMs last, before the actual artifact file. The reason for this, is to
122      * guarantee that scanner will provide only "best" informations 1st about same artifact, since the POM->artifact
123      * direction of discovery is not trivial at all (pom read -> packaging -> extension -> artifact file). The artifact
124      * -> POM direction is trivial.
125      */
126     private static class ScannerFileComparator
127         implements Comparator<File>
128     {
129         public int compare( File o1, File o2 )
130         {
131             if ( o1.getName().endsWith( ".pom" ) && !o2.getName().endsWith( ".pom" ) )
132             {
133                 // 1st is pom, 2nd is not
134                 return 1;
135             }
136             else if ( !o1.getName().endsWith( ".pom" ) && o2.getName().endsWith( ".pom" ) )
137             {
138                 // 2nd is pom, 1st is not
139                 return -1;
140             }
141             else
142             {
143                 // both are "same" (pom or not pom)
144                 // Use reverse order so that timestamped snapshots
145                 // use latest - not first
146                 return o2.getName().compareTo( o1.getName() );
147 
148             }
149         }
150     }
151 }