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.MalformedURLException;
021    import java.util.Collection;
022    import java.util.List;
023    import java.util.ArrayList;
024    import java.util.Collections;
025    import java.util.Map;
026    import java.util.HashMap;
027    import java.util.Arrays;
028    import java.io.IOException;
029    import java.io.File;
030    
031    /**
032     * @version $Rev$ $Date$
033     */
034    public 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            return excludePaths(System.getProperty("java.ext.dirs", ""));
109        }
110    
111        /**
112         * Calls excludePaths(System.getProperty("java.endorsed.dirs"))
113         *
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    
124            File java = new File(path);
125    
126            if (path.matches("/System/Library/Frameworks/JavaVM.framework/Versions/[^/]+/Home")){
127                java = java.getParentFile();
128            }
129    
130            return exclude(java);
131        }
132    
133        public UrlSet excludePaths(String pathString) throws MalformedURLException {
134            String[] paths = pathString.split(File.pathSeparator);
135            UrlSet urlSet = this;
136            for (String path : paths) {
137                File file = new File(path);
138                urlSet = urlSet.exclude(file);
139            }
140            return urlSet;
141        }
142    
143        public UrlSet matching(String pattern) {
144            Map<String, URL> urls = new HashMap<String, URL>();
145            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
146                String url = entry.getKey();
147                if (url.matches(pattern)){
148                    urls.put(url, entry.getValue());
149                }
150            }
151            return new UrlSet(urls);
152        }
153    
154        public UrlSet relative(File file) throws MalformedURLException {
155            String urlPath = file.toURL().toExternalForm();
156            Map<String, URL> urls = new HashMap<String, URL>();
157            for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
158                String url = entry.getKey();
159                if (url.startsWith(urlPath) || url.startsWith("jar:"+urlPath)){
160                    urls.put(url, entry.getValue());
161                }
162            }
163            return new UrlSet(urls);
164        }
165    
166        public List<URL> getUrls() {
167            return new ArrayList<URL>(urls.values());
168        }
169    
170        private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
171            List<URL> list = new ArrayList<URL>();
172            ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
173            for (URL url : urls) {
174                String externalForm = url.toExternalForm();
175                int i = externalForm.lastIndexOf("META-INF");
176                externalForm = externalForm.substring(0, i);
177                url = new URL(externalForm);
178                list.add(url);
179            }
180            list.addAll(Collections.list(classLoader.getResources("")));
181            return list;
182        }
183    }