001    /*
002     * Licensed under the Apache License, Version 2.0 (the "License");
003     * you may not use this file except in compliance with the License.
004     * You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS,
010     * WITHOUT WARRANTIES OR CODITIONS OF ANY KIND, either express or implied.
011     * See the License for the specific language governing permissions and
012     * limitations under the License.
013     */
014    
015    package org.apache.commons.classscan.builtin;
016    
017    import java.io.File;
018    import java.util.Collection;
019    import java.util.Iterator;
020    
021    import org.apache.commons.classscan.ClassFile;
022    import org.apache.commons.classscan.ResourceFile;
023    import org.apache.commons.classscan.spi.model.SpiClassPathElement;
024    import org.apache.commons.classscan.spi.model.SpiMetaRegistry;
025    
026    public class FileClassPathElement implements SpiClassPathElement {
027    
028            private final File baseLocation;
029            
030            FileClassPathElement(File baseLocation) {
031                    this.baseLocation= baseLocation;
032            }
033            
034            private static class FileCursor {
035                    final private FileCursor prior;
036                    final private File[] files;
037                    private int fileIdx;
038                    private final int priorLength;
039                    private final StringBuilder sb;
040            
041                    FileCursor(FileCursor prior, File dir, StringBuilder sb) {
042                            this.prior = prior;
043                            files= dir.listFiles();
044                            this.sb = sb;
045                            if(prior!=null) {
046                                    sb.append('/');
047                            }
048                            priorLength = sb.length();
049                    }
050    
051                    File nextFile() {
052                            if(fileIdx==files.length) {
053                                    return null;
054                            }
055                            File file = files[fileIdx++];
056                            sb.setLength(priorLength);
057                            sb.append(file.getName());
058                            return file;
059                    }
060                    
061                    FileCursor pop() {
062                            return prior;
063                    }
064            }
065            
066            @Override
067            public Iterator<ClassFile> iterator() {        
068    
069                    return new ClassFileIterator() {
070                            StringBuilder sb = new StringBuilder();
071                            FileCursor cursor= new FileCursor(null, baseLocation, sb);
072                            
073                            ClassFile getNext() {
074                                    for(;;) {
075                                            File file = cursor.nextFile();
076                                            if(file == null) {
077                                                    cursor = cursor.pop();
078                                                    if(cursor==null) {
079                                                            return null;
080                                                    }
081                                                    continue;
082                                            }
083                                            
084                                            String path = sb.toString();
085                                            if(file.isDirectory()) {
086                                                    String fileName = file.getName();
087                                                    if( ClassNameHelper.isValidIdentifier(fileName) ) {
088                                                            cursor= new FileCursor(cursor, file, sb);
089                                                    }
090                                                    continue;
091                                            }
092                                            
093                                            if(file.canRead()) {
094                                                    String className= ClassNameHelper.getClassNameFromFileName(file.getName());
095                                                    if(className!=null) {
096                                                            return new FileClassFile(file, path);
097                                                    }
098                                                    continue;
099                                            }
100                                    }
101                            }
102                    };
103            }
104    
105            @Override
106            public String getLocation() {
107                    return baseLocation.toURI().toString();
108            }
109    
110            @Override
111            public Collection<SpiClassPathElement> getAdditionalLocations(SpiMetaRegistry registry) {
112                    return null;
113            }
114    
115            @Override
116            public ResourceFile getResource(String fileName) {
117                    File file= new File(baseLocation, fileName);
118                    if(file.isFile()) {
119                            return new FileResourceFile(file, fileName);
120                    }
121                    return null;
122            }
123    }