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         *
115         * @return
116         * @throws MalformedURLException
117         */
118        public UrlSet excludeJavaEndorsedDirs() throws MalformedURLException {
119            return excludePaths(System.getProperty("java.endorsed.dirs", ""));
120        }
121    
122        public UrlSet excludeJavaHome() throws MalformedURLException {
123            String path = System.getProperty("java.home");
124            return exclude(new File(path));
125        }
126    
127        public UrlSet excludePaths(String pathString) throws MalformedURLException {
128            String[] paths = pathString.split(File.pathSeparator);
129            UrlSet urlSet = this;
130            for (String path : paths) {
131                File file = new File(path);
132                urlSet = urlSet.exclude(file);
133            }
134            return urlSet;
135        }
136    
137        public UrlSet matching(String pattern) {
138            Map<String, URL> urls = new HashMap<String, URL>();
139            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
140                String url = entry.getKey();
141                if (url.matches(pattern)){
142                    urls.put(url, entry.getValue());
143                }
144            }
145            return new UrlSet(urls);
146        }
147    
148        public UrlSet relative(File file) throws MalformedURLException {
149            String urlPath = file.toURL().toExternalForm();
150            Map<String, URL> urls = new HashMap<String, URL>();
151            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
152                String url = entry.getKey();
153                if (url.startsWith(urlPath) || url.startsWith("jar:"+urlPath)){
154                    urls.put(url, entry.getValue());
155                }
156            }
157            return new UrlSet(urls);
158        }
159    
160        public List<URL> getUrls() {
161            return new ArrayList<URL>(urls.values());
162        }
163    
164        private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
165            List<URL> list = new ArrayList<URL>();
166            ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
167            for (URL url : urls) {
168                String externalForm = url.toExternalForm();
169                int i = externalForm.lastIndexOf("META-INF");
170                externalForm = externalForm.substring(0, i);
171                url = new URL(externalForm);
172                list.add(url);
173            }
174            list.addAll(Collections.list(classLoader.getResources("")));
175            return list;
176        }
177    }