class DefaultClassScanner implements ClassScanner {

    @Override
    public Map<String, Class<?>> scan(ClassLoader loader) {
        Enumeration<URL> urls;
        URL url;
        String tmp;
        Map<String, Class<?>> parentClasses;
        File file;
        URI uri;
        
        synchronized (monitor) {
            if (classes == null) {
                classes = new TreeMap<String, Class<?>>();
                
                if (parent != null) {
                    if ((parentClasses = parent.scan(loader)) != null) {
                        classes.putAll(parentClasses);
                    }
                }
                
                try {
                    urls = loader.getResources("META-INF");
                    while (urls.hasMoreElements()) {
                        url = urls.nextElement();
                        tmp = url.toExternalForm();
                        tmp = tmp.substring(0, tmp.length() - 8);
                        LOGGER.debug("listClasses - source={}", tmp);
                        
                        try {
                            if (tmp.startsWith("file:")) {
                                uri = new URI(tmp);
                                if (sourceDirFilter == null || sourceDirFilter != null && sourceDirFilter.filter(uri)) {
                                    file = new File(uri);
                                    traverseFile(file.getAbsolutePath(), file, loader, classes);
                                }
                            } else if (tmp.startsWith("jar:")) {
                                uri = new URI(tmp.substring(4, tmp.length() - 2));
                                if (sourceDirFilter == null || sourceDirFilter != null && sourceDirFilter.filter(uri)) {
                                    file = new File(uri);
                                    traverseJar(file.getAbsolutePath(), file.toURI().toURL(), loader, classes);
                                }
                            }
                        } catch (URISyntaxException exception) {
                            LOGGER.debug("error while generating URI", exception);
                        }
                    }
                } catch (IOException exception) {
                    LOGGER.debug("error while traversing jar", exception);
                }
            }
        }
        
        return classes;
    }

    public  DefaultClassScanner();
    public  DefaultClassScanner(ClassScanner parent);
    public  DefaultClassScanner(GenericFilter<URI> sourceDirFilter, GenericFilter<String> classNameFilter);
    public  DefaultClassScanner(ClassScanner parent, GenericFilter<URI> sourceDirFilter, GenericFilter<String> classNameFilter);

}