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