1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 package net.sf.classifier4J.util;
53
54 import java.io.*;
55 import java.net.*;
56 import java.util.*;
57
58 /***
59 * <p>A class to locate resources, retrieve their contents, and determine their
60 * last modified time. To find the resource the class searches the CLASSPATH
61 * first, then Resource.class.getResource("/" + name). If the Resource finds
62 * a "file:" URL, the file path will be treated as a file. Otherwise, the
63 * path is treated as a URL and has limited last modified info.</p>
64 *
65 * <p>Heavily based on the example from http://www.onjava.com/pub/a/onjava/excerpt/jebp_3/index1.html?page=3#ex3-4</p>
66 *
67 */
68 public class Resource implements Serializable {
69
70 private String name;
71 private File file;
72 private URL url;
73
74 public Resource(String name) throws IOException {
75 this.name = name;
76 SecurityException exception = null;
77
78 try {
79
80
81 if (tryClasspath(name)) {
82 return;
83 }
84 } catch (SecurityException e) {
85 exception = e;
86 }
87
88 try {
89
90
91 if (tryLoader(name)) {
92 return;
93 }
94 } catch (SecurityException e) {
95 exception = e;
96 }
97
98
99 String msg = "";
100 if (exception != null) {
101 msg = ": " + exception;
102 }
103
104 throw new IOException("Resource '" + name + "' could not be found in " + "the CLASSPATH (" + System.getProperty("java.class.path") + "), nor could it be located by the classloader responsible for the " + "web application (WEB-INF/classes)" + msg);
105 }
106
107 /***
108 * Returns the resource name, as passed to the constructor
109 */
110 public String getName() {
111 return name;
112 }
113
114 /***
115 * Returns an input stream to read the resource contents
116 */
117 public InputStream getInputStream() throws IOException {
118 if (file != null) {
119 return new BufferedInputStream(new FileInputStream(file));
120 } else if (url != null) {
121 return new BufferedInputStream(url.openStream());
122 }
123 return null;
124 }
125
126 /***
127 * Returns when the resource was last modified. If the resource
128 * was found using a URL, this method will work only if the URL
129 * connection supports last modified information. If there's no
130 * support, Long.MAX_VALUE is returned. Perhaps this should return
131 * -1, but you should return MAX_VALUE on the assumption that if
132 * you can't determine the time, it's maximally new.
133 */
134 public long lastModified() {
135 if (file != null) {
136 return file.lastModified();
137 } else if (url != null) {
138 try {
139 return url.openConnection().getLastModified();
140 } catch (IOException e) {
141 return Long.MAX_VALUE;
142 }
143 }
144 return 0;
145 }
146
147 /***
148 * Returns the directory containing the resource, or null if the
149 * resource isn't directly available on the filesystem.
150 * This value can be used to locate the configuration file on disk,
151 * or to write files in the same directory.
152 */
153 public String getDirectory() {
154 if (file != null) {
155 return file.getParent();
156 } else if (url != null) {
157 return null;
158 }
159 return null;
160 }
161
162
163 private boolean tryClasspath(String filename) {
164 String classpath = System.getProperty("java.class.path");
165 String[] paths = split(classpath, File.pathSeparator);
166 file = searchDirectories(paths, filename);
167 return (file != null);
168 }
169
170 private static File searchDirectories(String[] paths, String filename) {
171 SecurityException exception = null;
172 for (int i = 0; i < paths.length; i++) {
173 try {
174 File file = new File(paths[i], filename);
175 if (file.exists() && !file.isDirectory()) {
176 return file;
177 }
178 } catch (SecurityException e) {
179
180
181 exception = e;
182 }
183 }
184
185 if (exception != null) {
186 throw exception;
187 } else {
188 return null;
189 }
190 }
191
192
193
194
195 private static String[] split(String str, String delim) {
196
197 Vector v = new Vector();
198
199
200 StringTokenizer tokenizer = new StringTokenizer(str, delim);
201 while (tokenizer.hasMoreTokens()) {
202 v.addElement(tokenizer.nextToken());
203 }
204
205 String[] ret = new String[v.size()];
206 v.copyInto(ret);
207 return ret;
208 }
209
210
211 private boolean tryLoader(String name) {
212 name = "/" + name;
213 URL res = Resource.class.getResource(name);
214 if (res == null) {
215 return false;
216 } else {
217
218 File resFile = urlToFile(res);
219 if (resFile != null) {
220 file = resFile;
221 } else {
222 url = res;
223 }
224 return true;
225 }
226
227 }
228
229 private static File urlToFile(URL res) {
230 String externalForm = res.toExternalForm();
231 if (externalForm.startsWith("file:")) {
232 return new File(externalForm.substring(5));
233 }
234 return null;
235 }
236
237 public String toString() {
238 return "[Resource: File: " + file + " URL: " + url + "]";
239 }
240 }