001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 */
017package org.apache.xbean.finder;
018
019import java.net.URL;
020import java.net.MalformedURLException;
021import java.util.Collection;
022import java.util.List;
023import java.util.ArrayList;
024import java.util.Collections;
025import java.util.Map;
026import java.util.HashMap;
027import java.util.Arrays;
028import java.io.IOException;
029import java.io.File;
030
031/**
032 * @version $Rev$ $Date$
033 */
034public class UrlSet {
035
036    private final Map<String,URL> urls;
037
038    public UrlSet(ClassLoader classLoader) throws IOException {
039        this(getUrls(classLoader));
040    }
041
042    public UrlSet(URL... urls){
043        this(Arrays.asList(urls));
044    }
045    /**
046     * Ignores all URLs that are not "jar" or "file"
047     * @param urls
048     */
049    public UrlSet(Collection<URL> urls){
050        this.urls = new HashMap<String,URL>();
051        for (URL location : urls) {
052            try {
053//                if (location.getProtocol().equals("file")) {
054//                    try {
055//                        // See if it's actually a jar
056//                        URL jarUrl = new URL("jar", "", location.toExternalForm() + "!/");
057//                        JarURLConnection juc = (JarURLConnection) jarUrl.openConnection();
058//                        juc.getJarFile();
059//                        location = jarUrl;
060//                    } catch (IOException e) {
061//                    }
062//                    this.urls.put(location.toExternalForm(), location);
063//                }
064                this.urls.put(location.toExternalForm(), location);
065            } catch (Exception e) {
066                e.printStackTrace();
067            }
068        }
069    }
070
071    private UrlSet(Map<String, URL> urls) {
072        this.urls = urls;
073    }
074
075    public UrlSet include(UrlSet urlSet){
076        Map<String, URL> urls = new HashMap<String, URL>(this.urls);
077        urls.putAll(urlSet.urls);
078        return new UrlSet(urls);
079    }
080
081    public UrlSet exclude(UrlSet urlSet) {
082        Map<String, URL> urls = new HashMap<String, URL>(this.urls);
083        Map<String, URL> parentUrls = urlSet.urls;
084        for (String url : parentUrls.keySet()) {
085            urls.remove(url);
086        }
087        return new UrlSet(urls);
088    }
089
090    public UrlSet exclude(ClassLoader parent) throws IOException {
091        return exclude(new UrlSet(parent));
092    }
093
094    public UrlSet exclude(File file) throws MalformedURLException {
095        return exclude(relative(file));
096    }
097
098    public UrlSet exclude(String pattern) throws MalformedURLException {
099        return exclude(matching(pattern));
100    }
101
102    /**
103     * Calls excludePaths(System.getProperty("java.ext.dirs"))
104     * @return
105     * @throws MalformedURLException
106     */
107    public UrlSet excludeJavaExtDirs() throws MalformedURLException {
108        String extDirs = System.getProperty("java.ext.dirs");
109        return extDirs == null ? this : excludePaths(extDirs);
110    }
111
112    /**
113     * Calls excludePaths(System.getProperty("java.endorsed.dirs"))
114     *
115     * @return
116     * @throws MalformedURLException
117     */
118    public UrlSet excludeJavaEndorsedDirs() throws MalformedURLException {
119        String endorsedDirs = System.getProperty("java.endorsed.dirs");
120        return endorsedDirs == null ? this : excludePaths(endorsedDirs);
121    }
122
123    public UrlSet excludeJavaHome() throws MalformedURLException {
124        String path = System.getProperty("java.home");
125
126        File java = new File(path);
127
128        if (path.matches("/System/Library/Frameworks/JavaVM.framework/Versions/[^/]+/Home")){
129            java = java.getParentFile();
130        }
131
132        return exclude(java);
133    }
134
135    public UrlSet excludePaths(String pathString) throws MalformedURLException {
136        String[] paths = pathString.split(File.pathSeparator);
137        UrlSet urlSet = this;
138        for (String path : paths) {
139            File file = new File(path);
140            urlSet = urlSet.exclude(file);
141        }
142        return urlSet;
143    }
144
145    public UrlSet matching(String pattern) {
146        Map<String, URL> urls = new HashMap<String, URL>();
147        for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
148            String url = entry.getKey();
149            if (url.matches(pattern)){
150                urls.put(url, entry.getValue());
151            }
152        }
153        return new UrlSet(urls);
154    }
155
156    public UrlSet relative(File file) throws MalformedURLException {
157        String urlPath = file.toURI().toURL().toExternalForm();
158        Map<String, URL> urls = new HashMap<String, URL>();
159        for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
160            String url = entry.getKey();
161            if (url.startsWith(urlPath) || url.startsWith("jar:"+urlPath)){
162                urls.put(url, entry.getValue());
163            }
164        }
165        return new UrlSet(urls);
166    }
167
168    public List<URL> getUrls() {
169        return new ArrayList<URL>(urls.values());
170    }
171
172    private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
173        List<URL> list = new ArrayList<URL>();
174        ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
175        for (URL url : urls) {
176            String externalForm = url.toExternalForm();
177            int i = externalForm.lastIndexOf("META-INF");
178            externalForm = externalForm.substring(0, i);
179            url = new URL(externalForm);
180            list.add(url);
181        }
182        list.addAll(Collections.list(classLoader.getResources("")));
183        return list;
184    }
185}