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     */
017    package org.apache.xbean.finder;
018    
019    import java.net.URL;
020    import java.net.JarURLConnection;
021    import java.net.MalformedURLException;
022    import java.util.Collection;
023    import java.util.List;
024    import java.util.ArrayList;
025    import java.util.Collections;
026    import java.util.Map;
027    import java.util.HashMap;
028    import java.util.Arrays;
029    import java.io.IOException;
030    import java.io.File;
031    
032    /**
033     * @version $Rev$ $Date$
034     */
035    public class UrlSet {
036    
037        private final Map<String,URL> urls;
038    
039        public UrlSet(ClassLoader classLoader) throws IOException {
040            this(getUrls(classLoader));
041        }
042    
043        public UrlSet(URL... urls){
044            this(Arrays.asList(urls));
045        }
046        /**
047         * Ignores all URLs that are not "jar" or "file"
048         * @param urls
049         */
050        public UrlSet(Collection<URL> urls){
051            this.urls = new HashMap<String,URL>();
052            for (URL location : urls) {
053                try {
054    //                if (location.getProtocol().equals("file")) {
055    //                    try {
056    //                        // See if it's actually a jar
057    //                        URL jarUrl = new URL("jar", "", location.toExternalForm() + "!/");
058    //                        JarURLConnection juc = (JarURLConnection) jarUrl.openConnection();
059    //                        juc.getJarFile();
060    //                        location = jarUrl;
061    //                    } catch (IOException e) {
062    //                    }
063    //                    this.urls.put(location.toExternalForm(), location);
064    //                }
065                    this.urls.put(location.toExternalForm(), location);
066                } catch (Exception e) {
067                    e.printStackTrace();
068                }
069            }
070        }
071    
072        private UrlSet(Map<String, URL> urls) {
073            this.urls = urls;
074        }
075    
076        public UrlSet include(UrlSet urlSet){
077            Map<String, URL> urls = new HashMap<String, URL>(this.urls);
078            urls.putAll(urlSet.urls);
079            return new UrlSet(urls);
080        }
081    
082        public UrlSet exclude(UrlSet urlSet) {
083            Map<String, URL> urls = new HashMap<String, URL>(this.urls);
084            Map<String, URL> parentUrls = urlSet.urls;
085            for (String url : parentUrls.keySet()) {
086                urls.remove(url);
087            }
088            return new UrlSet(urls);
089        }
090    
091        public UrlSet exclude(ClassLoader parent) throws IOException {
092            return exclude(new UrlSet(parent));
093        }
094    
095        public UrlSet exclude(File file) throws MalformedURLException {
096            return exclude(relative(file));
097        }
098    
099        public UrlSet exclude(String pattern) throws MalformedURLException {
100            return exclude(matching(pattern));
101        }
102    
103        /**
104         * Calls excludePaths(System.getProperty("java.ext.dirs"))
105         * @return
106         * @throws MalformedURLException
107         */
108        public UrlSet excludeJavaExtDirs() throws MalformedURLException {
109            return excludePaths(System.getProperty("java.ext.dirs"));
110        }
111    
112        /**
113         * Calls excludePaths(System.getProperty("java.endorsed.dirs"))
114         * @return
115         * @throws MalformedURLException
116         */
117        public UrlSet excludeJavaEndorsedDirs() throws MalformedURLException {
118            return excludePaths(System.getProperty("java.endorsed.dirs"));
119        }
120    
121        public UrlSet excludeJavaHome() throws MalformedURLException {
122            String path = System.getProperty("java.home");
123            return exclude(new File(path));
124        }
125    
126        public UrlSet excludePaths(String pathString) throws MalformedURLException {
127            String[] paths = pathString.split(File.pathSeparator);
128            UrlSet urlSet = this;
129            for (String path : paths) {
130                File file = new File(path);
131                urlSet = urlSet.exclude(file);
132            }
133            return urlSet;
134        }
135    
136        public UrlSet matching(String pattern) {
137            Map<String, URL> urls = new HashMap<String, URL>();
138            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
139                String url = entry.getKey();
140                if (url.matches(pattern)){
141                    urls.put(url, entry.getValue());
142                }
143            }
144            return new UrlSet(urls);
145        }
146    
147        public UrlSet relative(File file) throws MalformedURLException {
148            String urlPath = file.toURL().toExternalForm();
149            Map<String, URL> urls = new HashMap<String, URL>();
150            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
151                String url = entry.getKey();
152                if (url.startsWith(urlPath) || url.startsWith("jar:"+urlPath)){
153                    urls.put(url, entry.getValue());
154                }
155            }
156            return new UrlSet(urls);
157        }
158    
159        public List<URL> getUrls() {
160            return new ArrayList<URL>(urls.values());
161        }
162    
163        private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
164            List<URL> list = new ArrayList<URL>();
165            ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
166            for (URL url : urls) {
167                String externalForm = url.toExternalForm();
168                int i = externalForm.lastIndexOf("META-INF");
169                externalForm = externalForm.substring(0, i);
170                url = new URL(externalForm);
171                list.add(url);
172            }
173            list.addAll(Collections.list(classLoader.getResources("")));
174            return list;
175        }
176    }