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 org.apache.xbean.finder.filter.Filter;
020
021 import java.net.URL;
022 import java.net.MalformedURLException;
023 import java.util.Collection;
024 import java.util.Iterator;
025 import java.util.List;
026 import java.util.ArrayList;
027 import java.util.Collections;
028 import java.util.Map;
029 import java.util.HashMap;
030 import java.util.Arrays;
031 import java.io.IOException;
032 import java.io.File;
033
034 import static org.apache.xbean.finder.filter.Filters.invert;
035 import static org.apache.xbean.finder.filter.Filters.patterns;
036
037 /**
038 * @version $Rev$ $Date$
039 */
040 public class UrlSet implements Iterable<URL> {
041
042 private final Map<String,URL> urls;
043
044 public UrlSet(ClassLoader classLoader) throws IOException {
045 this(getUrls(classLoader));
046 }
047
048 public UrlSet(URL... urls){
049 this(Arrays.asList(urls));
050 }
051 /**
052 * Ignores all URLs that are not "jar" or "file"
053 * @param urls
054 */
055 public UrlSet(Collection<URL> urls){
056 this.urls = new HashMap<String,URL>();
057 for (URL location : urls) {
058 try {
059 // if (location.getProtocol().equals("file")) {
060 // try {
061 // // See if it's actually a jar
062 // URL jarUrl = new URL("jar", "", location.toExternalForm() + "!/");
063 // JarURLConnection juc = (JarURLConnection) jarUrl.openConnection();
064 // juc.getJarFile();
065 // location = jarUrl;
066 // } catch (IOException e) {
067 // }
068 // this.urls.put(location.toExternalForm(), location);
069 // }
070 this.urls.put(location.toExternalForm(), location);
071 } catch (Exception e) {
072 e.printStackTrace();
073 }
074 }
075 }
076
077 private UrlSet(Map<String, URL> urls) {
078 this.urls = urls;
079 }
080
081 public UrlSet include(UrlSet urlSet){
082 Map<String, URL> urls = new HashMap<String, URL>(this.urls);
083 urls.putAll(urlSet.urls);
084 return new UrlSet(urls);
085 }
086
087
088 public UrlSet include(URL url){
089 Map<String, URL> urls = new HashMap<String, URL>(this.urls);
090 urls.put(url.toExternalForm(), url);
091 return new UrlSet(urls);
092 }
093
094 public UrlSet exclude(UrlSet urlSet) {
095 Map<String, URL> urls = new HashMap<String, URL>(this.urls);
096 Map<String, URL> parentUrls = urlSet.urls;
097 for (String url : parentUrls.keySet()) {
098 urls.remove(url);
099 }
100 return new UrlSet(urls);
101 }
102
103 public UrlSet exclude(URL url) {
104 Map<String, URL> urls = new HashMap<String, URL>(this.urls);
105 urls.remove(url.toExternalForm());
106 return new UrlSet(urls);
107 }
108
109 public UrlSet exclude(ClassLoader parent) throws IOException {
110 return exclude(new UrlSet(parent));
111 }
112
113 public UrlSet exclude(File file) throws MalformedURLException {
114 return exclude(relative(file));
115 }
116
117 public UrlSet exclude(String pattern) throws MalformedURLException {
118 return filter(invert(patterns(pattern)));
119 }
120
121 /**
122 * Calls excludePaths(System.getProperty("java.ext.dirs"))
123 * @return
124 * @throws MalformedURLException
125 */
126 public UrlSet excludeJavaExtDirs() throws MalformedURLException {
127 String extDirs = System.getProperty("java.ext.dirs");
128 return extDirs == null ? this : excludePaths(extDirs);
129 }
130
131 /**
132 * Calls excludePaths(System.getProperty("java.endorsed.dirs"))
133 *
134 * @return
135 * @throws MalformedURLException
136 */
137 public UrlSet excludeJavaEndorsedDirs() throws MalformedURLException {
138 String endorsedDirs = System.getProperty("java.endorsed.dirs");
139 return endorsedDirs == null ? this : excludePaths(endorsedDirs);
140 }
141
142 public UrlSet excludeJavaHome() throws MalformedURLException {
143 String path = System.getProperty("java.home");
144
145 File java = new File(path);
146
147 if (path.matches("/System/Library/Frameworks/JavaVM.framework/Versions/[^/]+/Home")){
148 java = java.getParentFile();
149 }
150
151 return exclude(java);
152 }
153
154 public UrlSet excludePaths(String pathString) throws MalformedURLException {
155 String[] paths = pathString.split(File.pathSeparator);
156 UrlSet urlSet = this;
157 for (String path : paths) {
158 File file = new File(path);
159 urlSet = urlSet.exclude(file);
160 }
161 return urlSet;
162 }
163
164 public UrlSet filter(Filter filter) {
165 Map<String, URL> urls = new HashMap<String, URL>();
166 for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
167 String url = entry.getKey();
168 if (filter.accept(url)){
169 urls.put(url, entry.getValue());
170 }
171 }
172 return new UrlSet(urls);
173 }
174
175 public UrlSet matching(String pattern) {
176 return filter(patterns(pattern));
177 }
178
179 public UrlSet relative(File file) throws MalformedURLException {
180 String urlPath = file.toURI().toURL().toExternalForm();
181 Map<String, URL> urls = new HashMap<String, URL>();
182 for (Map.Entry<String, URL> entry : this.urls.entrySet()) {
183 String url = entry.getKey();
184 if (url.startsWith(urlPath) || url.startsWith("jar:"+urlPath)){
185 urls.put(url, entry.getValue());
186 }
187 }
188 return new UrlSet(urls);
189 }
190
191 public List<URL> getUrls() {
192 return new ArrayList<URL>(urls.values());
193 }
194
195 public int size() {
196 return urls.size();
197 }
198
199 @Override
200 public Iterator<URL> iterator() {
201 return getUrls().iterator();
202 }
203
204 private static List<URL> getUrls(ClassLoader classLoader) throws IOException {
205 List<URL> list = new ArrayList<URL>();
206 ArrayList<URL> urls = Collections.list(classLoader.getResources("META-INF"));
207 for (URL url : urls) {
208 String externalForm = url.toExternalForm();
209 int i = externalForm.lastIndexOf("META-INF");
210 externalForm = externalForm.substring(0, i);
211 url = new URL(externalForm);
212 list.add(url);
213 }
214 list.addAll(Collections.list(classLoader.getResources("")));
215 return list;
216 }
217
218 @Override
219 public String toString() {
220 return super.toString() + "[" + urls.size() + "]";
221 }
222 }