1 package org.djutils.io;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.Authenticator;
7 import java.net.MalformedURLException;
8 import java.net.PasswordAuthentication;
9 import java.net.URL;
10
11 /**
12 * The URLResource class helps to resolve a file location in a project, JAR, or folder. The static methods return a URL of the
13 * file location that was found, or null in case it was not found.
14 * <p>
15 * Copyright (c) 2002-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
16 * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
17 * distributed under a three-clause BSD-style license, which can be found at
18 * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
19 * </p>
20 * @author Peter Jacobs
21 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
22 */
23 public final class URLResource
24 {
25 /**
26 * constructs a new URLResource.
27 */
28 private URLResource()
29 {
30 super();
31 // unreachable code
32 }
33
34 /**
35 * Resolves a resource for name.
36 * @param name String; the name to search for
37 * @return the resolved URL
38 */
39 public static URL getResource(final String name)
40 {
41 try
42 {
43 File file = new File(name);
44
45 if (name.startsWith("/"))
46 {
47 URL url = URLResource.class.getResource(name);
48 if (url != null)
49 {
50 return url;
51 }
52 url = Thread.currentThread().getContextClassLoader().getResource(name.substring(1));
53 if (url != null)
54 {
55 return url;
56 }
57 if (file.exists())
58 {
59 return new URL("file:" + name);
60 }
61 }
62 else if (name.startsWith("\\") || name.contains("\\")) // added the second part
63 {
64 if (file.exists())
65 {
66 return new URL("file:" + name);
67 }
68 }
69 else if (file.exists())
70 {
71 return new URL("file:" + name);
72 }
73 else
74 {
75 if (name.indexOf("@") == -1)
76 {
77 return new URL(name);
78 }
79 // we need authentication
80 String temp = name.substring(name.indexOf("//") + 2);
81 String userName = temp.substring(0, temp.indexOf(":"));
82 String password = temp.substring(temp.indexOf(":") + 1);
83 password = password.substring(0, password.indexOf("@"));
84 String url = name.substring(0, name.indexOf("//") + 2);
85 url = url + name.substring(name.indexOf("@") + 1);
86 Authenticator.setDefault(new PasswordAuthenticator(userName, password));
87 return new URL(url);
88 }
89 }
90 catch (Exception exception)
91 {
92 exception = null;
93 // We neglect exceptions since we return null
94 }
95 return null;
96 }
97
98 /**
99 * Resolves a resource for name. For relative names, base is used to resolve to an absolute name. If name is absolute, base
100 * is ignored.
101 * @param name String; the name to search for
102 * @param base String; the base for relative paths
103 * @return the resolved URL
104 */
105 public static URL getResource(final String name, final String base)
106 {
107 URL url = null;
108
109 // case complete URL
110 try
111 {
112 url = new URL(name);
113 }
114 catch (MalformedURLException ex)
115 {
116 // neglect exception -- just trying
117 }
118
119 // absolute or relative case
120 if (url == null)
121 {
122 String completeName = name;
123 if (!name.startsWith(File.separator) && !name.startsWith("/") && base != null)
124 {
125 String baseDir = "";
126 int i = base.lastIndexOf(File.separator);
127 if (i == -1 && !File.separator.equals("/"))
128 {
129 i = base.lastIndexOf("/");
130 }
131 if (i != -1)
132 {
133 baseDir = base.substring(0, i + 1);
134 }
135 completeName = baseDir + name;
136 }
137
138 // case base = URL
139 try
140 {
141 url = new URL(completeName);
142 if (url.getProtocol().equalsIgnoreCase("file"))
143 {
144 File file = new File(url.getPath());
145 if (!file.exists())
146 {
147 url = null;
148 }
149 }
150 }
151 catch (MalformedURLException ex)
152 {
153 url = getResourceOrFile(completeName);
154 }
155
156 // just try plain name if that's still another option
157 if (url == null && !name.equalsIgnoreCase(completeName))
158 {
159 url = getResourceOrFile(name);
160 }
161
162 }
163
164 // handle authentication
165 if (url != null && url.getUserInfo() != null)
166 {
167 String ui = url.getUserInfo();
168 String userName = ui.substring(0, ui.indexOf(":"));
169 String password = ui.substring(ui.indexOf(":") + 1);
170 Authenticator.setDefault(new PasswordAuthenticator(userName, password));
171 }
172
173 return url;
174 }
175
176 /**
177 * Resolves a resource for a path.
178 * @param path String; the path to search for
179 * @return the resolved URL to the path
180 */
181 private static URL getResourceOrFile(String path)
182 {
183 URL url = null;
184
185 // resource
186 if (url == null)
187 {
188 url = URLResource.class.getResource(path);
189 }
190
191 // thread context resource
192 if (url == null)
193 {
194 url = Thread.currentThread().getContextClassLoader().getResource(path.substring(1));
195 }
196
197 // file
198 if (url == null)
199 {
200 File file = new File(path);
201 if (file.exists())
202 {
203 try
204 {
205 url = new URL("file:" + file.getCanonicalPath());
206 }
207 catch (IOException ex)
208 {
209 // ignore -- if not found, we return null
210 }
211 }
212 }
213
214 return url;
215 }
216
217 /**
218 * returns the resource as stream.
219 * @param name String; the name of the resource
220 * @return the inputStream
221 */
222 public static InputStream getResourceAsStream(final String name)
223 {
224 try
225 {
226 URL url = URLResource.getResource(name);
227 if (url == null)
228 {
229 return null;
230 }
231 return url.openStream();
232 }
233 catch (Exception exception)
234 {
235 return null;
236 }
237 }
238
239 /**
240 * A Private password authenticator.
241 */
242 private static class PasswordAuthenticator extends Authenticator
243 {
244 /** my user name. */
245 private String userName = null;
246
247 /** my password. */
248 private String password = null;
249
250 /**
251 * constructs a new PasswordAuthenticator.
252 * @param userName String; my userName
253 * @param password String; my passWord
254 */
255 public PasswordAuthenticator(final String userName, final String password)
256 {
257 super();
258 this.userName = userName;
259 this.password = password;
260 }
261
262 /** {@inheritDoc} */
263 @Override
264 protected PasswordAuthentication getPasswordAuthentication()
265 {
266 return new PasswordAuthentication(this.userName, this.password.toCharArray());
267 }
268 }
269
270 }