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 }