View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.index;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
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 implements Scanner {
42  
43      private final ArtifactContextProducer artifactContextProducer;
44  
45      @Inject
46      public DefaultScanner(ArtifactContextProducer artifactContextProducer) {
47          this.artifactContextProducer = artifactContextProducer;
48      }
49  
50      public ScanningResult scan(ScanningRequest request) {
51          request.getArtifactScanningListener().scanningStarted(request.getIndexingContext());
52  
53          ScanningResult result = new ScanningResult(request);
54  
55          scanDirectory(request.getStartingDirectory(), request);
56  
57          request.getArtifactScanningListener().scanningFinished(request.getIndexingContext(), result);
58  
59          return result;
60      }
61  
62      private void scanDirectory(File dir, ScanningRequest request) {
63          if (dir == null) {
64              return;
65          }
66  
67          File[] fileArray = dir.listFiles();
68  
69          if (fileArray != null) {
70              Set<File> files = new TreeSet<>(new ScannerFileComparator());
71  
72              files.addAll(Arrays.asList(fileArray));
73  
74              for (File f : files) {
75                  if (f.getName().startsWith(".")) {
76                      continue; // skip all hidden files and directories
77                  }
78  
79                  if (f.isDirectory()) {
80                      scanDirectory(f, request);
81                  }
82                  // else if ( !AbstractIndexCreator.isIndexable( f ) )
83                  // {
84                  // continue; // skip non-indexable files
85                  // }
86                  else {
87                      processFile(f, request);
88                  }
89              }
90          }
91      }
92  
93      private void processFile(File file, ScanningRequest request) {
94          IndexingContext context = request.getIndexingContext();
95  
96          ArtifactContext ac = artifactContextProducer.getArtifactContext(context, file);
97  
98          if (ac != null) {
99              request.getArtifactScanningListener().artifactDiscovered(ac);
100         }
101     }
102 
103     // ==
104 
105     /**
106      * A special comparator to overcome some very bad limitations of nexus-indexer during scanning: using this
107      * comparator, we force to "discover" POMs last, before the actual artifact file. The reason for this, is to
108      * guarantee that scanner will provide only "best" informations 1st about same artifact, since the POM->artifact
109      * direction of discovery is not trivial at all (pom read -> packaging -> extension -> artifact file). The artifact
110      * -> POM direction is trivial.
111      */
112     private static class ScannerFileComparator implements Comparator<File> {
113         public int compare(File o1, File o2) {
114             if (o1.getName().endsWith(".pom") && !o2.getName().endsWith(".pom")) {
115                 // 1st is pom, 2nd is not
116                 return 1;
117             } else if (!o1.getName().endsWith(".pom") && o2.getName().endsWith(".pom")) {
118                 // 2nd is pom, 1st is not
119                 return -1;
120             } else {
121                 // both are "same" (pom or not pom)
122                 // Use reverse order so that timestamped snapshots
123                 // use latest - not first
124                 return o2.getName().compareTo(o1.getName());
125             }
126         }
127     }
128 }