author | chegar |
Fri, 16 Sep 2011 12:09:04 -0700 | |
changeset 10596 | 39b3a979e600 |
parent 7668 | d4a77089c587 |
child 23886 | 6cb6ad1e208f |
permissions | -rw-r--r-- |
2 | 1 |
/* |
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
7668
diff
changeset
|
2 |
* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.net.www; |
|
27 |
import java.io.*; |
|
28 |
import java.net.FileNameMap; |
|
29 |
import java.util.Hashtable; |
|
30 |
import java.util.Enumeration; |
|
31 |
import java.util.Properties; |
|
32 |
import java.util.StringTokenizer; |
|
33 |
||
34 |
public class MimeTable implements FileNameMap { |
|
35 |
/** Keyed by content type, returns MimeEntries */ |
|
51 | 36 |
private Hashtable<String, MimeEntry> entries |
37 |
= new Hashtable<String, MimeEntry>(); |
|
2 | 38 |
|
39 |
/** Keyed by file extension (with the .), returns MimeEntries */ |
|
51 | 40 |
private Hashtable<String, MimeEntry> extensionMap |
41 |
= new Hashtable<String, MimeEntry>(); |
|
2 | 42 |
|
43 |
// Will be reset if in the platform-specific data file |
|
44 |
private static String tempFileTemplate; |
|
45 |
||
46 |
static { |
|
47 |
java.security.AccessController.doPrivileged( |
|
51 | 48 |
new java.security.PrivilegedAction<Void>() { |
49 |
public Void run() { |
|
2 | 50 |
tempFileTemplate = |
51 |
System.getProperty("content.types.temp.file.template", |
|
52 |
"/tmp/%s"); |
|
53 |
||
54 |
mailcapLocations = new String[] { |
|
55 |
System.getProperty("user.mailcap"), |
|
56 |
System.getProperty("user.home") + "/.mailcap", |
|
57 |
"/etc/mailcap", |
|
58 |
"/usr/etc/mailcap", |
|
59 |
"/usr/local/etc/mailcap", |
|
60 |
System.getProperty("hotjava.home", |
|
51 | 61 |
"/usr/local/hotjava") |
62 |
+ "/lib/mailcap", |
|
2 | 63 |
}; |
64 |
return null; |
|
65 |
} |
|
66 |
}); |
|
67 |
} |
|
68 |
||
69 |
||
70 |
private static final String filePreamble = "sun.net.www MIME content-types table"; |
|
71 |
private static final String fileMagic = "#" + filePreamble; |
|
72 |
||
73 |
MimeTable() { |
|
74 |
load(); |
|
75 |
} |
|
76 |
||
6887 | 77 |
private static class DefaultInstanceHolder { |
78 |
static final MimeTable defaultInstance = getDefaultInstance(); |
|
79 |
||
80 |
static MimeTable getDefaultInstance() { |
|
81 |
return java.security.AccessController.doPrivileged( |
|
82 |
new java.security.PrivilegedAction<MimeTable>() { |
|
83 |
public MimeTable run() { |
|
84 |
MimeTable instance = new MimeTable(); |
|
85 |
URLConnection.setFileNameMap(instance); |
|
86 |
return instance; |
|
87 |
} |
|
88 |
}); |
|
89 |
} |
|
90 |
} |
|
91 |
||
2 | 92 |
/** |
93 |
* Get the single instance of this class. First use will load the |
|
94 |
* table from a data file. |
|
95 |
*/ |
|
96 |
public static MimeTable getDefaultTable() { |
|
6887 | 97 |
return DefaultInstanceHolder.defaultInstance; |
2 | 98 |
} |
99 |
||
100 |
/** |
|
101 |
* |
|
102 |
*/ |
|
103 |
public static FileNameMap loadTable() { |
|
104 |
MimeTable mt = getDefaultTable(); |
|
105 |
return (FileNameMap)mt; |
|
106 |
} |
|
107 |
||
108 |
public synchronized int getSize() { |
|
109 |
return entries.size(); |
|
110 |
} |
|
111 |
||
112 |
public synchronized String getContentTypeFor(String fileName) { |
|
113 |
MimeEntry entry = findByFileName(fileName); |
|
114 |
if (entry != null) { |
|
115 |
return entry.getType(); |
|
116 |
} else { |
|
117 |
return null; |
|
118 |
} |
|
119 |
} |
|
120 |
||
121 |
public synchronized void add(MimeEntry m) { |
|
122 |
entries.put(m.getType(), m); |
|
123 |
||
124 |
String exts[] = m.getExtensions(); |
|
125 |
if (exts == null) { |
|
126 |
return; |
|
127 |
} |
|
128 |
||
129 |
for (int i = 0; i < exts.length; i++) { |
|
130 |
extensionMap.put(exts[i], m); |
|
131 |
} |
|
132 |
} |
|
133 |
||
134 |
public synchronized MimeEntry remove(String type) { |
|
51 | 135 |
MimeEntry entry = entries.get(type); |
2 | 136 |
return remove(entry); |
137 |
} |
|
138 |
||
139 |
public synchronized MimeEntry remove(MimeEntry entry) { |
|
140 |
String[] extensionKeys = entry.getExtensions(); |
|
141 |
if (extensionKeys != null) { |
|
142 |
for (int i = 0; i < extensionKeys.length; i++) { |
|
143 |
extensionMap.remove(extensionKeys[i]); |
|
144 |
} |
|
145 |
} |
|
146 |
||
51 | 147 |
return entries.remove(entry.getType()); |
2 | 148 |
} |
149 |
||
150 |
public synchronized MimeEntry find(String type) { |
|
51 | 151 |
MimeEntry entry = entries.get(type); |
2 | 152 |
if (entry == null) { |
153 |
// try a wildcard lookup |
|
51 | 154 |
Enumeration<MimeEntry> e = entries.elements(); |
2 | 155 |
while (e.hasMoreElements()) { |
51 | 156 |
MimeEntry wild = e.nextElement(); |
2 | 157 |
if (wild.matches(type)) { |
158 |
return wild; |
|
159 |
} |
|
160 |
} |
|
161 |
} |
|
162 |
||
163 |
return entry; |
|
164 |
} |
|
165 |
||
166 |
/** |
|
167 |
* Locate a MimeEntry by the file extension that has been associated |
|
168 |
* with it. Parses general file names, and URLs. |
|
169 |
*/ |
|
170 |
public MimeEntry findByFileName(String fname) { |
|
171 |
String ext = ""; |
|
172 |
||
173 |
int i = fname.lastIndexOf('#'); |
|
174 |
||
175 |
if (i > 0) { |
|
176 |
fname = fname.substring(0, i - 1); |
|
177 |
} |
|
178 |
||
179 |
i = fname.lastIndexOf('.'); |
|
180 |
// REMIND: OS specific delimters appear here |
|
181 |
i = Math.max(i, fname.lastIndexOf('/')); |
|
182 |
i = Math.max(i, fname.lastIndexOf('?')); |
|
183 |
||
184 |
if (i != -1 && fname.charAt(i) == '.') { |
|
185 |
ext = fname.substring(i).toLowerCase(); |
|
186 |
} |
|
187 |
||
188 |
return findByExt(ext); |
|
189 |
} |
|
190 |
||
191 |
/** |
|
192 |
* Locate a MimeEntry by the file extension that has been associated |
|
193 |
* with it. |
|
194 |
*/ |
|
195 |
public synchronized MimeEntry findByExt(String fileExtension) { |
|
51 | 196 |
return extensionMap.get(fileExtension); |
2 | 197 |
} |
198 |
||
199 |
public synchronized MimeEntry findByDescription(String description) { |
|
51 | 200 |
Enumeration<MimeEntry> e = elements(); |
2 | 201 |
while (e.hasMoreElements()) { |
51 | 202 |
MimeEntry entry = e.nextElement(); |
2 | 203 |
if (description.equals(entry.getDescription())) { |
204 |
return entry; |
|
205 |
} |
|
206 |
} |
|
207 |
||
208 |
// We failed, now try treating description as type |
|
209 |
return find(description); |
|
210 |
} |
|
211 |
||
212 |
String getTempFileTemplate() { |
|
213 |
return tempFileTemplate; |
|
214 |
} |
|
215 |
||
51 | 216 |
public synchronized Enumeration<MimeEntry> elements() { |
2 | 217 |
return entries.elements(); |
218 |
} |
|
219 |
||
220 |
// For backward compatibility -- mailcap format files |
|
221 |
// This is not currently used, but may in the future when we add ability |
|
222 |
// to read BOTH the properties format and the mailcap format. |
|
223 |
protected static String[] mailcapLocations; |
|
224 |
||
225 |
public synchronized void load() { |
|
226 |
Properties entries = new Properties(); |
|
227 |
File file = null; |
|
228 |
try { |
|
229 |
InputStream is; |
|
230 |
// First try to load the user-specific table, if it exists |
|
231 |
String userTablePath = |
|
232 |
System.getProperty("content.types.user.table"); |
|
233 |
if (userTablePath != null) { |
|
234 |
file = new File(userTablePath); |
|
235 |
if (!file.exists()) { |
|
236 |
// No user-table, try to load the default built-in table. |
|
237 |
file = new File(System.getProperty("java.home") + |
|
238 |
File.separator + |
|
239 |
"lib" + |
|
240 |
File.separator + |
|
241 |
"content-types.properties"); |
|
242 |
} |
|
243 |
} |
|
244 |
else { |
|
245 |
// No user table, try to load the default built-in table. |
|
246 |
file = new File(System.getProperty("java.home") + |
|
247 |
File.separator + |
|
248 |
"lib" + |
|
249 |
File.separator + |
|
250 |
"content-types.properties"); |
|
251 |
} |
|
252 |
||
253 |
is = new BufferedInputStream(new FileInputStream(file)); |
|
254 |
entries.load(is); |
|
255 |
is.close(); |
|
256 |
} |
|
257 |
catch (IOException e) { |
|
258 |
System.err.println("Warning: default mime table not found: " + |
|
259 |
file.getPath()); |
|
260 |
return; |
|
261 |
} |
|
262 |
parse(entries); |
|
263 |
} |
|
264 |
||
265 |
void parse(Properties entries) { |
|
266 |
// first, strip out the platform-specific temp file template |
|
267 |
String tempFileTemplate = (String)entries.get("temp.file.template"); |
|
268 |
if (tempFileTemplate != null) { |
|
269 |
entries.remove("temp.file.template"); |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
7668
diff
changeset
|
270 |
MimeTable.tempFileTemplate = tempFileTemplate; |
2 | 271 |
} |
272 |
||
273 |
// now, parse the mime-type spec's |
|
51 | 274 |
Enumeration<?> types = entries.propertyNames(); |
2 | 275 |
while (types.hasMoreElements()) { |
276 |
String type = (String)types.nextElement(); |
|
277 |
String attrs = entries.getProperty(type); |
|
278 |
parse(type, attrs); |
|
279 |
} |
|
280 |
} |
|
281 |
||
282 |
// |
|
283 |
// Table format: |
|
284 |
// |
|
285 |
// <entry> ::= <table_tag> | <type_entry> |
|
286 |
// |
|
287 |
// <table_tag> ::= <table_format_version> | <temp_file_template> |
|
288 |
// |
|
289 |
// <type_entry> ::= <type_subtype_pair> '=' <type_attrs_list> |
|
290 |
// |
|
291 |
// <type_subtype_pair> ::= <type> '/' <subtype> |
|
292 |
// |
|
293 |
// <type_attrs_list> ::= <attr_value_pair> [ ';' <attr_value_pair> ]* |
|
294 |
// | [ <attr_value_pair> ]+ |
|
295 |
// |
|
296 |
// <attr_value_pair> ::= <attr_name> '=' <attr_value> |
|
297 |
// |
|
298 |
// <attr_name> ::= 'description' | 'action' | 'application' |
|
299 |
// | 'file_extensions' | 'icon' |
|
300 |
// |
|
301 |
// <attr_value> ::= <legal_char>* |
|
302 |
// |
|
303 |
// Embedded ';' in an <attr_value> are quoted with leading '\' . |
|
304 |
// |
|
305 |
// Interpretation of <attr_value> depends on the <attr_name> it is |
|
306 |
// associated with. |
|
307 |
// |
|
308 |
||
309 |
void parse(String type, String attrs) { |
|
310 |
MimeEntry newEntry = new MimeEntry(type); |
|
311 |
||
312 |
// REMIND handle embedded ';' and '|' and literal '"' |
|
313 |
StringTokenizer tokenizer = new StringTokenizer(attrs, ";"); |
|
314 |
while (tokenizer.hasMoreTokens()) { |
|
315 |
String pair = tokenizer.nextToken(); |
|
316 |
parse(pair, newEntry); |
|
317 |
} |
|
318 |
||
319 |
add(newEntry); |
|
320 |
} |
|
321 |
||
322 |
void parse(String pair, MimeEntry entry) { |
|
323 |
// REMIND add exception handling... |
|
324 |
String name = null; |
|
325 |
String value = null; |
|
326 |
||
327 |
boolean gotName = false; |
|
328 |
StringTokenizer tokenizer = new StringTokenizer(pair, "="); |
|
329 |
while (tokenizer.hasMoreTokens()) { |
|
330 |
if (gotName) { |
|
331 |
value = tokenizer.nextToken().trim(); |
|
332 |
} |
|
333 |
else { |
|
334 |
name = tokenizer.nextToken().trim(); |
|
335 |
gotName = true; |
|
336 |
} |
|
337 |
} |
|
338 |
||
339 |
fill(entry, name, value); |
|
340 |
} |
|
341 |
||
342 |
void fill(MimeEntry entry, String name, String value) { |
|
343 |
if ("description".equalsIgnoreCase(name)) { |
|
344 |
entry.setDescription(value); |
|
345 |
} |
|
346 |
else if ("action".equalsIgnoreCase(name)) { |
|
347 |
entry.setAction(getActionCode(value)); |
|
348 |
} |
|
349 |
else if ("application".equalsIgnoreCase(name)) { |
|
350 |
entry.setCommand(value); |
|
351 |
} |
|
352 |
else if ("icon".equalsIgnoreCase(name)) { |
|
353 |
entry.setImageFileName(value); |
|
354 |
} |
|
355 |
else if ("file_extensions".equalsIgnoreCase(name)) { |
|
356 |
entry.setExtensions(value); |
|
357 |
} |
|
358 |
||
359 |
// else illegal name exception |
|
360 |
} |
|
361 |
||
362 |
String[] getExtensions(String list) { |
|
363 |
StringTokenizer tokenizer = new StringTokenizer(list, ","); |
|
364 |
int n = tokenizer.countTokens(); |
|
365 |
String[] extensions = new String[n]; |
|
366 |
for (int i = 0; i < n; i++) { |
|
367 |
extensions[i] = tokenizer.nextToken(); |
|
368 |
} |
|
369 |
||
370 |
return extensions; |
|
371 |
} |
|
372 |
||
373 |
int getActionCode(String action) { |
|
374 |
for (int i = 0; i < MimeEntry.actionKeywords.length; i++) { |
|
375 |
if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) { |
|
376 |
return i; |
|
377 |
} |
|
378 |
} |
|
379 |
||
380 |
return MimeEntry.UNKNOWN; |
|
381 |
} |
|
382 |
||
383 |
public synchronized boolean save(String filename) { |
|
384 |
if (filename == null) { |
|
385 |
filename = System.getProperty("user.home" + |
|
386 |
File.separator + |
|
387 |
"lib" + |
|
388 |
File.separator + |
|
389 |
"content-types.properties"); |
|
390 |
} |
|
391 |
||
392 |
return saveAsProperties(new File(filename)); |
|
393 |
} |
|
394 |
||
395 |
public Properties getAsProperties() { |
|
396 |
Properties properties = new Properties(); |
|
51 | 397 |
Enumeration<MimeEntry> e = elements(); |
2 | 398 |
while (e.hasMoreElements()) { |
51 | 399 |
MimeEntry entry = e.nextElement(); |
2 | 400 |
properties.put(entry.getType(), entry.toProperty()); |
401 |
} |
|
402 |
||
403 |
return properties; |
|
404 |
} |
|
405 |
||
406 |
protected boolean saveAsProperties(File file) { |
|
407 |
FileOutputStream os = null; |
|
408 |
try { |
|
409 |
os = new FileOutputStream(file); |
|
410 |
Properties properties = getAsProperties(); |
|
411 |
properties.put("temp.file.template", tempFileTemplate); |
|
412 |
String tag; |
|
413 |
String user = System.getProperty("user.name"); |
|
414 |
if (user != null) { |
|
415 |
tag = "; customized for " + user; |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
7668
diff
changeset
|
416 |
properties.store(os, filePreamble + tag); |
2 | 417 |
} |
418 |
else { |
|
10596
39b3a979e600
7090158: Networking Libraries don't build with javac -Werror
chegar
parents:
7668
diff
changeset
|
419 |
properties.store(os, filePreamble); |
2 | 420 |
} |
421 |
} |
|
422 |
catch (IOException e) { |
|
423 |
e.printStackTrace(); |
|
424 |
return false; |
|
425 |
} |
|
426 |
finally { |
|
427 |
if (os != null) { |
|
428 |
try { os.close(); } catch (IOException e) {} |
|
429 |
} |
|
430 |
} |
|
431 |
||
432 |
return true; |
|
433 |
} |
|
434 |
/* |
|
435 |
* Debugging utilities |
|
436 |
* |
|
437 |
public void list(PrintStream out) { |
|
438 |
Enumeration keys = entries.keys(); |
|
439 |
while (keys.hasMoreElements()) { |
|
440 |
String key = (String)keys.nextElement(); |
|
441 |
MimeEntry entry = (MimeEntry)entries.get(key); |
|
442 |
out.println(key + ": " + entry); |
|
443 |
} |
|
444 |
} |
|
445 |
||
446 |
public static void main(String[] args) { |
|
447 |
MimeTable testTable = MimeTable.getDefaultTable(); |
|
448 |
||
449 |
Enumeration e = testTable.elements(); |
|
450 |
while (e.hasMoreElements()) { |
|
451 |
MimeEntry entry = (MimeEntry)e.nextElement(); |
|
452 |
System.out.println(entry); |
|
453 |
} |
|
454 |
||
455 |
testTable.save(File.separator + "tmp" + |
|
456 |
File.separator + "mime_table.save"); |
|
457 |
} |
|
458 |
*/ |
|
459 |
} |