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 CONDITIONS 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    package org.apache.commons.classscan.builtin;
015    
016    import java.io.IOException;
017    import java.net.URL;
018    import java.net.URLClassLoader;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Map;
025    
026    import org.apache.commons.classscan.ClassPathElement;
027    import org.apache.commons.classscan.ResourceFile;
028    import org.apache.commons.classscan.spi.model.SpiClassPath;
029    import org.apache.commons.classscan.spi.model.SpiClassPathElement;
030    import org.apache.commons.classscan.spi.model.SpiMetaClassLoader;
031    import org.apache.commons.classscan.spi.model.SpiMetaRegistry;
032    import org.slf4j.Logger;
033    import org.slf4j.LoggerFactory;
034    
035    public class UrlClassPath implements SpiClassPath {
036    
037        private static final Logger logger = LoggerFactory.getLogger(UrlClassPath.class);
038    
039        private final SpiMetaRegistry registry;
040            private final List<SpiClassPathElement> classPathElements;
041            
042            public UrlClassPath(SpiMetaRegistry registry, URLClassLoader urlClassLoader) {
043                    this.registry = registry;
044                    classPathElements = Collections.unmodifiableList(getClassPathElements(registry, urlClassLoader.getURLs()));
045            }
046    
047            static List<SpiClassPathElement> getClassPathElements(SpiMetaRegistry registry, URL[] urls) {
048                    List<SpiClassPathElement> elements = new ArrayList<SpiClassPathElement>();
049                    Map<String, URL> locations = new HashMap<String, URL>();
050                    for(URL url : urls) {
051                            String baseLocation= url.toExternalForm();
052                            if( locations.containsKey(baseLocation) ) {
053                                    continue;
054                            }
055                            locations.put(baseLocation, url);
056                            
057                            try {
058                                    SpiClassPathElement element= registry.createClassPathElement(url);
059                                    elements.add(element);
060                            } catch (IOException e) {
061                            logger.info("Problem with URL "+url, e);
062                            }
063                    }
064                    return elements;
065            }
066    
067            @Override
068            public List<? extends ClassPathElement> getClassPathElements() {
069                    return classPathElements;
070            }
071    
072            @Override
073            public SpiMetaClassLoader createMetaClassLoader(SpiMetaRegistry registry, ClassLoader classLoader) {
074                    return new UrlMetaClassLoader(registry, classLoader);
075            }
076    
077            @Override
078            public Map<ClassPathElement, ResourceFile> getResources(String fileName) {
079                    Map<ClassPathElement, ResourceFile> resources = new HashMap<ClassPathElement, ResourceFile>();
080                    Map<String,ClassPathElement> visited = new HashMap<String,ClassPathElement>();
081                    searchElements(visited, resources, classPathElements, fileName);
082                    return resources;
083            }
084            
085            public void searchElements(Map<String,ClassPathElement> visited, Map<ClassPathElement, ResourceFile> resources, Collection<SpiClassPathElement> elements, String fileName) {
086                    for(SpiClassPathElement element : elements) {
087                            String location = element.getLocation();
088                            if(visited.put(location, element)!=null) {
089                                    continue;
090                            }
091    
092                            ResourceFile resource= element.getResource(fileName);
093                            if(resource!=null) {
094                                    resources.put(element, resource);
095                            }
096                            
097                            Collection<SpiClassPathElement> additionalLocations = element.getAdditionalLocations(registry);
098                            if(additionalLocations!=null) {
099                                    searchElements(visited, resources, additionalLocations, fileName);
100                            }
101                    }
102            }
103    }