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            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    }