1:
37:
38: package ;
39:
40: import ;
41:
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58:
73: public class MailcapCommandMap
74: extends CommandMap
75: {
76:
77: private static final int PROG = 0;
78: private static final int HOME = 1;
79: private static final int SYS = 2;
80: private static final int JAR = 3;
81: private static final int DEF = 4;
82: private static boolean debug = false;
83: private static final int NORMAL = 0;
84: private static final int FALLBACK = 1;
85:
86: static
87: {
88: try
89: {
90: String d = System.getProperty("javax.activation.debug");
91: debug = Boolean.valueOf(d).booleanValue();
92: }
93: catch (SecurityException e)
94: {
95: }
96: }
97:
98: private Map<String,Map<String,List<String>>>[][] mailcaps;
99:
100:
103: public MailcapCommandMap()
104: {
105: init(null);
106: }
107:
108:
112: public MailcapCommandMap(String fileName)
113: throws IOException
114: {
115: Reader in = null;
116: try
117: {
118: in = new FileReader(fileName);
119: }
120: catch (IOException e)
121: {
122: }
123: init(in);
124: if (in != null)
125: {
126: try
127: {
128: in.close();
129: }
130: catch (IOException e)
131: {
132: }
133: }
134: }
135:
136:
140: public MailcapCommandMap(InputStream is)
141: {
142: init(new InputStreamReader(is));
143: }
144:
145: private void init(Reader in)
146: {
147: mailcaps = new Map[5][2];
148: for (int i = 0; i < 5; i++)
149: {
150: for (int j = 0; j < 2; j++)
151: {
152: mailcaps[i][j] =
153: new LinkedHashMap<String,Map<String,List<String>>>();
154: }
155: }
156: if (in != null)
157: {
158: if (debug)
159: {
160: System.out.println("MailcapCommandMap: load PROG");
161: }
162: try
163: {
164: parse(PROG, in);
165: }
166: catch (IOException e)
167: {
168: }
169: }
170:
171: if (debug)
172: {
173: System.out.println("MailcapCommandMap: load HOME");
174: }
175: try
176: {
177: String home = System.getProperty("user.home");
178: if (home != null)
179: {
180: parseFile(HOME, new CPStringBuilder(home)
181: .append(File.separatorChar)
182: .append(".mailcap")
183: .toString());
184: }
185: }
186: catch (SecurityException e)
187: {
188: }
189:
190: if (debug)
191: {
192: System.out.println("MailcapCommandMap: load SYS");
193: }
194: try
195: {
196: parseFile(SYS,
197: new CPStringBuilder(System.getProperty("java.home"))
198: .append(File.separatorChar)
199: .append("lib")
200: .append(File.separatorChar)
201: .append("mailcap")
202: .toString());
203: }
204: catch (SecurityException e)
205: {
206: }
207:
208: if (debug)
209: {
210: System.out.println("MailcapCommandMap: load JAR");
211: }
212: List<URL> systemResources = getSystemResources("META-INF/mailcap");
213: int len = systemResources.size();
214: if (len > 0)
215: {
216: for (int i = 0; i < len ; i++)
217: {
218: Reader urlIn = null;
219: URL url = systemResources.get(i);
220: try
221: {
222: if (debug)
223: {
224: System.out.println("\t" + url.toString());
225: }
226: urlIn = new InputStreamReader(url.openStream());
227: parse(JAR, urlIn);
228: }
229: catch (IOException e)
230: {
231: if (debug)
232: {
233: System.out.println(e.getClass().getName() + ": " +
234: e.getMessage());
235: }
236: }
237: finally
238: {
239: if (urlIn != null)
240: {
241: try
242: {
243: urlIn.close();
244: }
245: catch (IOException e)
246: {
247: }
248: }
249: }
250: }
251: }
252: else
253: {
254: parseResource(JAR, "/META-INF/mailcap");
255: }
256:
257: if (debug)
258: {
259: System.out.println("MailcapCommandMap: load DEF");
260: }
261: parseResource(DEF, "/META-INF/mailcap.default");
262: }
263:
264:
268: public synchronized CommandInfo[] getPreferredCommands(String mimeType)
269: {
270: List<CommandInfo> cmdList = new ArrayList<CommandInfo>();
271: List<String> verbList = new ArrayList<String>();
272: for (int i = 0; i < 2; i++)
273: {
274: for (int j = 0; j < 5; j++)
275: {
276: Map<String,List<String>> map = getCommands(mailcaps[j][i], mimeType);
277: if (map != null)
278: {
279: for (Map.Entry<String,List<String>> entry : map.entrySet())
280: {
281: String verb = entry.getKey();
282: if (!verbList.contains(verb))
283: {
284: List<String> classNames = entry.getValue();
285: String className = classNames.get(0);
286: CommandInfo cmd = new CommandInfo(verb, className);
287: cmdList.add(cmd);
288: verbList.add(verb);
289: }
290: }
291: }
292: }
293: }
294: CommandInfo[] cmds = new CommandInfo[cmdList.size()];
295: cmdList.toArray(cmds);
296: return cmds;
297: }
298:
299:
303: public synchronized CommandInfo[] getAllCommands(String mimeType)
304: {
305: List<CommandInfo> cmdList = new ArrayList<CommandInfo>();
306: for (int i = 0; i < 2; i++)
307: {
308: for (int j = 0; j < 5; j++)
309: {
310: Map<String,List<String>> map = getCommands(mailcaps[j][i], mimeType);
311: if (map != null)
312: {
313: for (Map.Entry<String,List<String>> entry : map.entrySet())
314: {
315: String verb = entry.getKey();
316: List<String> classNames = entry.getValue();
317: int len = classNames.size();
318: for (int l = 0; l < len; l++)
319: {
320: String className = classNames.get(l);
321: CommandInfo cmd = new CommandInfo(verb, className);
322: cmdList.add(cmd);
323: }
324: }
325: }
326: }
327: }
328: CommandInfo[] cmds = new CommandInfo[cmdList.size()];
329: cmdList.toArray(cmds);
330: return cmds;
331: }
332:
333:
338: public synchronized CommandInfo getCommand(String mimeType,
339: String cmdName)
340: {
341: for (int i = 0; i < 2; i++)
342: {
343: for (int j = 0; j < 5; j++)
344: {
345: Map<String,List<String>> map =
346: getCommands(mailcaps[j][i], mimeType);
347: if (map != null)
348: {
349: List<String> classNames = map.get(cmdName);
350: if (classNames == null)
351: {
352: classNames = map.get("x-java-" + cmdName);
353: }
354: if (classNames != null)
355: {
356: String className = classNames.get(0);
357: return new CommandInfo(cmdName, className);
358: }
359: }
360: }
361: }
362: return null;
363: }
364:
365:
369: public synchronized void addMailcap(String mailcap)
370: {
371: if (debug)
372: {
373: System.out.println("MailcapCommandMap: add to PROG");
374: }
375: try
376: {
377: parse(PROG, new StringReader(mailcap));
378: }
379: catch (IOException e)
380: {
381: }
382: }
383:
384:
388: public synchronized DataContentHandler
389: createDataContentHandler(String mimeType)
390: {
391: if (debug)
392: {
393: System.out.println("MailcapCommandMap: " +
394: "createDataContentHandler for " + mimeType);
395: }
396: for (int i = 0; i < 2; i++)
397: {
398: for (int j = 0; j < 5; j++)
399: {
400: if (debug)
401: {
402: System.out.println(" search DB #" + i);
403: }
404: Map<String,List<String>> map = getCommands(mailcaps[j][i], mimeType);
405: if (map != null)
406: {
407: List<String> classNames = map.get("content-handler");
408: if (classNames == null)
409: {
410: classNames = map.get("x-java-content-handler");
411: }
412: if (classNames != null)
413: {
414: String className = classNames.get(0);
415: if (debug)
416: {
417: System.out.println(" In " + nameOf(j) +
418: ", content-handler=" + className);
419: }
420: try
421: {
422: Class<?> clazz = Class.forName(className);
423: return (DataContentHandler)clazz.newInstance();
424: }
425: catch (IllegalAccessException e)
426: {
427: if (debug)
428: {
429: e.printStackTrace();
430: }
431: }
432: catch (ClassNotFoundException e)
433: {
434: if (debug)
435: {
436: e.printStackTrace();
437: }
438: }
439: catch (InstantiationException e)
440: {
441: if (debug)
442: {
443: e.printStackTrace();
444: }
445: }
446: }
447: }
448: }
449: }
450: return null;
451: }
452:
453:
466: public String[] getNativeCommands(String mimeType)
467: {
468: List<String> acc = new ArrayList<String>();
469: for (int i = 0; i < 2; i++)
470: {
471: for (int j = 0; j < 5; j++)
472: {
473: addNativeCommands(acc, mailcaps[j][i], mimeType);
474: }
475: }
476: String[] ret = new String[acc.size()];
477: acc.toArray(ret);
478: return ret;
479: }
480:
481: private void addNativeCommands(List<String> acc,
482: Map<String,Map<String,List<String>>> mailcap,
483: String mimeType)
484: {
485: for (Map.Entry<String,Map<String,List<String>>> mEntry : mailcap.entrySet())
486: {
487: String entryMimeType = mEntry.getKey();
488: if (!entryMimeType.equals(mimeType))
489: {
490: continue;
491: }
492: Map<String,List<String>> commands = mEntry.getValue();
493: String viewCommand = commands.get("view-command").get(0);
494: if (viewCommand == null)
495: {
496: continue;
497: }
498: CPStringBuilder buf = new CPStringBuilder();
499: buf.append(mimeType);
500: buf.append(';');
501: buf.append(' ');
502: buf.append(viewCommand);
503: for (Map.Entry<String,List<String>> cEntry : commands.entrySet())
504: {
505: String verb = cEntry.getKey();
506: List<String> classNames = cEntry.getValue();
507: if (!"view-command".equals(verb))
508: {
509: for (String command : classNames)
510: {
511: buf.append(';');
512: buf.append(' ');
513: buf.append(verb);
514: buf.append('=');
515: buf.append(command);
516: }
517: }
518: }
519: if (buf.length() > 0)
520: {
521: acc.add(buf.toString());
522: }
523: }
524: }
525:
526: private static String nameOf(int mailcap)
527: {
528: switch (mailcap)
529: {
530: case PROG:
531: return "PROG";
532: case HOME:
533: return "HOME";
534: case SYS:
535: return "SYS";
536: case JAR:
537: return "JAR";
538: case DEF:
539: return "DEF";
540: default:
541: return "ERR";
542: }
543: }
544:
545: private void parseFile(int index, String filename)
546: {
547: Reader in = null;
548: try
549: {
550: if (debug)
551: {
552: System.out.println("\t" + filename);
553: }
554: in = new FileReader(filename);
555: parse(index, in);
556: }
557: catch (IOException e)
558: {
559: if (debug)
560: {
561: System.out.println(e.getClass().getName() + ": " +
562: e.getMessage());
563: }
564: }
565: finally
566: {
567: if (in != null)
568: {
569: try
570: {
571: in.close();
572: }
573: catch (IOException e)
574: {
575: }
576: }
577: }
578: }
579:
580: private void parseResource(int index, String name)
581: {
582: Reader in = null;
583: try
584: {
585: InputStream is = getClass().getResourceAsStream(name);
586: if (is != null)
587: {
588: if (debug)
589: {
590: System.out.println("\t" + name);
591: }
592: in = new InputStreamReader(is);
593: parse(index, in);
594: }
595: }
596: catch (IOException e)
597: {
598: if (debug)
599: {
600: System.out.println(e.getClass().getName() + ": " +
601: e.getMessage());
602: }
603: }
604: finally
605: {
606: if (in != null)
607: {
608: try
609: {
610: in.close();
611: }
612: catch (IOException e)
613: {
614: }
615: }
616: }
617: }
618:
619: private void parse(int index, Reader in)
620: throws IOException
621: {
622: BufferedReader br = new BufferedReader(in);
623: CPStringBuilder buf = null;
624: for (String line = br.readLine(); line != null; line = br.readLine())
625: {
626: line = line.trim();
627: int len = line.length();
628: if (len == 0 || line.charAt(0) == '#')
629: {
630: continue;
631: }
632: if (line.charAt(len - 1) == '\\')
633: {
634: if (buf == null)
635: {
636: buf = new CPStringBuilder();
637: }
638: buf.append(line.substring(0, len - 1));
639: }
640: else if (buf != null)
641: {
642: buf.append(line);
643: parseEntry(index, buf.toString());
644: buf = null;
645: }
646: else
647: {
648: parseEntry(index, line);
649: }
650: }
651: }
652:
653: private void parseEntry(int index, String line)
654: {
655:
656: char[] chars = line.toCharArray();
657: int len = chars.length;
658: boolean inQuotedString = false;
659: boolean fallback = false;
660: CPStringBuilder buffer = new CPStringBuilder();
661: List<String> fields = new ArrayList<String>();
662: for (int i = 0; i < len; i++)
663: {
664: char c = chars[i];
665: if (c == '\\')
666: {
667: c = chars[++i];
668: }
669: if (c == ';' && !inQuotedString)
670: {
671: String field = buffer.toString().trim();
672: if ("x-java-fallback-entry".equals(field))
673: {
674: fallback = true;
675: }
676: fields.add(field);
677: buffer.setLength(0);
678: }
679: else
680: {
681: if (c == '"')
682: {
683: inQuotedString = !inQuotedString;
684: }
685: buffer.append(c);
686: }
687: }
688: String field = buffer.toString().trim();
689: if ("x-java-fallback-entry".equals(field))
690: {
691: fallback = true;
692: }
693: fields.add(field);
694:
695: len = fields.size();
696: if (len < 2)
697: {
698: if (debug)
699: {
700: System.err.println("Invalid mailcap entry: " + line);
701: }
702: return;
703: }
704:
705: Map<String,Map<String,List<String>>> mailcap =
706: fallback ? mailcaps[index][FALLBACK] : mailcaps[index][NORMAL];
707: String mimeType = fields.get(0);
708: addField(mailcap, mimeType, "view-command", (String) fields.get(1));
709: for (int i = 2; i < len; i++)
710: {
711: addField(mailcap, mimeType, null, (String) fields.get(i));
712: }
713: }
714:
715: private void addField(Map<String,Map<String,List<String>>> mailcap,
716: String mimeType, String verb, String command)
717: {
718: if (verb == null)
719: {
720: int ei = command.indexOf('=');
721: if (ei != -1)
722: {
723: verb = command.substring(0, ei);
724: command = command.substring(ei + 1);
725: }
726: }
727: if (command.length() == 0 || verb == null || verb.length() == 0)
728: {
729: return;
730: }
731:
732: Map<String,List<String>> commands = mailcap.get(mimeType);
733: if (commands == null)
734: {
735: commands = new LinkedHashMap<String,List<String>>();
736: mailcap.put(mimeType, commands);
737: }
738: List<String> classNames = commands.get(verb);
739: if (classNames == null)
740: {
741: classNames = new ArrayList<String>();
742: commands.put(verb, classNames);
743: }
744: classNames.add(command);
745: }
746:
747: private Map<String,List<String>>
748: getCommands(Map<String,Map<String,List<String>>> mailcap,
749: String mimeType)
750: {
751: int si = mimeType.indexOf('/');
752: String genericMimeType = new CPStringBuilder(mimeType.substring(0, si))
753: .append('/')
754: .append('*')
755: .toString();
756: Map<String,List<String>> specific = mailcap.get(mimeType);
757: Map<String,List<String>> generic = mailcap.get(genericMimeType);
758: if (generic == null)
759: {
760: return specific;
761: }
762: if (specific == null)
763: {
764: return generic;
765: }
766: Map<String,List<String>> combined = new LinkedHashMap<String,List<String>>();
767: combined.putAll(specific);
768: for (String verb : generic.keySet())
769: {
770: List<String> genericClassNames = generic.get(verb);
771: List<String> classNames = combined.get(verb);
772: if (classNames == null)
773: {
774: combined.put(verb, genericClassNames);
775: }
776: else
777: {
778: classNames.addAll(genericClassNames);
779: }
780: }
781: return combined;
782: }
783:
784:
785:
786: private List<URL> getSystemResources(String name)
787: {
788: List<URL> acc = new ArrayList<URL>();
789: try
790: {
791: for (Enumeration<URL> i = ClassLoader.getSystemResources(name);
792: i.hasMoreElements(); )
793: {
794: acc.add(i.nextElement());
795: }
796: }
797: catch (IOException e)
798: {
799: }
800: return acc;
801: }
802:
803: }