FileDocCategorySizeDatePackage
MailcapFile.javaAPI DocGlassfish v2 API18974Mon May 14 15:29:52 BST 2007com.sun.activation.registries

MailcapFile

public class MailcapFile extends Object

Fields Summary
private Map
type_hash
A Map indexed by MIME type (string) that references a Map of commands for each type. The comand Map is indexed by the command name and references a List of class names (strings) for each command.
private Map
fallback_hash
Another Map like above, but for fallback entries.
private Map
native_commands
A Map indexed by MIME type (string) that references a List of native commands (string) corresponding to the type.
private static boolean
addReverse
Constructors Summary
public MailcapFile(String new_fname)
The constructor that takes a filename as an argument.

param
new_fname The file name of the mailcap file.


     
	try {
	    addReverse = Boolean.getBoolean("javax.activation.addreverse");
	} catch (Throwable t) {
	    // ignore any errors
	}
    
	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: file " + new_fname);
	FileReader reader = null;
	try {
	    reader = new FileReader(new_fname);
	    parse(new BufferedReader(reader));
	} finally {
	    if (reader != null) {
		try {
		    reader.close();
		} catch (IOException ex) { }
	    }
	}
    
public MailcapFile(InputStream is)
The constructor that takes an input stream as an argument.

param
is the input stream

	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: InputStream");
	parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1")));
    
public MailcapFile()
Mailcap file default constructor.

	if (LogSupport.isLoggable())
	    LogSupport.log("new MailcapFile: default");
    
Methods Summary
public voidappendToMailcap(java.lang.String mail_cap)
appendToMailcap: Append to this Mailcap DB, use the mailcap format: Comment == "# comment string Entry == "mimetype; javabeanclass Example: # this is a comment image/gif jaf.viewers.ImageViewer

	if (LogSupport.isLoggable())
	    LogSupport.log("appendToMailcap: " + mail_cap);
	try {
	    parse(new StringReader(mail_cap));
	} catch (IOException ex) {
	    // can't happen
	}
    
public java.util.MapgetMailcapFallbackList(java.lang.String mime_type)
Get the Map of fallback MailcapEntries based on the MIME type.

Semantics: First check for the literal mime type, if that fails looks for wildcard /\* and return that. Return the list of all that hit.

	Map search_result = null;
	Map wildcard_result = null;

	// first try the literal
	search_result = (Map)fallback_hash.get(mime_type);

	// ok, now try the wildcard
	int separator = mime_type.indexOf('/");
	String subtype = mime_type.substring(separator + 1);
	if (!subtype.equals("*")) {
	    String type = mime_type.substring(0, separator + 1) + "*";
	    wildcard_result = (Map)fallback_hash.get(type);

	    if (wildcard_result != null) { // damn, we have to merge!!!
		if (search_result != null)
		    search_result =
			mergeResults(search_result, wildcard_result);
		else
		    search_result = wildcard_result;
	    }
	}
	return search_result;
    
public java.util.MapgetMailcapList(java.lang.String mime_type)
Get the Map of MailcapEntries based on the MIME type.

Semantics: First check for the literal mime type, if that fails looks for wildcard /\* and return that. Return the list of all that hit.

	Map search_result = null;
	Map wildcard_result = null;

	// first try the literal
	search_result = (Map)type_hash.get(mime_type);

	// ok, now try the wildcard
	int separator = mime_type.indexOf('/");
	String subtype = mime_type.substring(separator + 1);
	if (!subtype.equals("*")) {
	    String type = mime_type.substring(0, separator + 1) + "*";
	    wildcard_result = (Map)type_hash.get(type);

	    if (wildcard_result != null) { // damn, we have to merge!!!
		if (search_result != null)
		    search_result =
			mergeResults(search_result, wildcard_result);
		else
		    search_result = wildcard_result;
	    }
	}
	return search_result;
    
public java.lang.String[]getMimeTypes()
Return all the MIME types known to this mailcap file.

	Set types = new HashSet(type_hash.keySet());
	types.addAll(fallback_hash.keySet());
	types.addAll(native_commands.keySet());
	String[] mts = new String[types.size()];
	mts = (String[])types.toArray(mts);
	return mts;
    
public java.lang.String[]getNativeCommands(java.lang.String mime_type)
Return all the native comands for the given MIME type.

	String[] cmds = null;
	List v =
	    (List)native_commands.get(mime_type.toLowerCase(Locale.ENGLISH));
	if (v != null) {
	    cmds = new String[v.size()];
	    cmds = (String[])v.toArray(cmds);
	}
	return cmds;
    
private java.util.MapmergeResults(java.util.Map first, java.util.Map second)
Merge the first hash into the second. This merge will only effect the hashtable that is returned, we don't want to touch the one passed in since its integrity must be maintained.

	Iterator verb_enum = second.keySet().iterator();
	Map clonedHash = new HashMap(first);

	// iterate through the verbs in the second map
	while (verb_enum.hasNext()) {
	    String verb = (String)verb_enum.next();
	    List cmdVector = (List)clonedHash.get(verb);
	    if (cmdVector == null) {
		clonedHash.put(verb, second.get(verb));
	    } else {
		// merge the two
		List oldV = (List)second.get(verb);
		cmdVector = new ArrayList(cmdVector);
		cmdVector.addAll(oldV);
		clonedHash.put(verb, cmdVector);
	    }
	}
	return clonedHash;
    
private voidparse(java.io.Reader reader)
parse file into a hash table of MC Type Entry Obj

	BufferedReader buf_reader = new BufferedReader(reader);
	String line = null;
	String continued = null;

	while ((line = buf_reader.readLine()) != null) {
	    //    LogSupport.log("parsing line: " + line);

	    line = line.trim();

	    try {
		if (line.charAt(0) == '#")
		    continue;
		if (line.charAt(line.length() - 1) == '\\") {
		    if (continued != null)
			continued += line.substring(0, line.length() - 1);
		    else
			continued = line.substring(0, line.length() - 1);
		} else if (continued != null) {
		    // handle the two strings
		    continued = continued + line;
		    //	LogSupport.log("parse: " + continued);
		    try {
			parseLine(continued);
		    } catch (MailcapParseException e) {
			//e.printStackTrace();
		    }
		    continued = null;
		}
		else {
		    //	LogSupport.log("parse: " + line);
		    try {
			parseLine(line);
			// LogSupport.log("hash.size = " + type_hash.size());
		    } catch (MailcapParseException e) {
			//e.printStackTrace();
		    }
		}
	    } catch (StringIndexOutOfBoundsException e) {}
	}
    
protected voidparseLine(java.lang.String mailcapEntry)
A routine to parse individual entries in a Mailcap file. Note that this routine does not handle line continuations. They should have been handled prior to calling this routine.

	MailcapTokenizer tokenizer = new MailcapTokenizer(mailcapEntry);
	tokenizer.setIsAutoquoting(false);

	if (LogSupport.isLoggable())
	    LogSupport.log("parse: " + mailcapEntry);
	//	parse the primary type
	int currentToken = tokenizer.nextToken();
	if (currentToken != MailcapTokenizer.STRING_TOKEN) {
	    reportParseError(MailcapTokenizer.STRING_TOKEN, currentToken,
					tokenizer.getCurrentTokenValue());
	}
	String primaryType =
	    tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH);
	String subType = "*";

	//	parse the '/' between primary and sub
	//	if it's not present that's ok, we just don't have a subtype
	currentToken = tokenizer.nextToken();
	if ((currentToken != MailcapTokenizer.SLASH_TOKEN) &&
			(currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) {
	    reportParseError(MailcapTokenizer.SLASH_TOKEN,
				MailcapTokenizer.SEMICOLON_TOKEN, currentToken,
				tokenizer.getCurrentTokenValue());
	}

	//	only need to look for a sub type if we got a '/'
	if (currentToken == MailcapTokenizer.SLASH_TOKEN) {
	    //	parse the sub type
	    currentToken = tokenizer.nextToken();
	    if (currentToken != MailcapTokenizer.STRING_TOKEN) {
		reportParseError(MailcapTokenizer.STRING_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
	    }
	    subType =
		tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH);

	    //	get the next token to simplify the next step
	    currentToken = tokenizer.nextToken();
	}

	String mimeType = primaryType + "/" + subType;

	if (LogSupport.isLoggable())
	    LogSupport.log("  Type: " + mimeType);

	//	now setup the commands hashtable
	Map commands = new LinkedHashMap();	// keep commands in order found

	//	parse the ';' that separates the type from the parameters
	if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) {
	    reportParseError(MailcapTokenizer.SEMICOLON_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
	}
	//	eat it

	//	parse the required view command
	tokenizer.setIsAutoquoting(true);
	currentToken = tokenizer.nextToken();
	tokenizer.setIsAutoquoting(false);
	if ((currentToken != MailcapTokenizer.STRING_TOKEN) &&
		    (currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) {
	    reportParseError(MailcapTokenizer.STRING_TOKEN,
			    MailcapTokenizer.SEMICOLON_TOKEN, currentToken,
			    tokenizer.getCurrentTokenValue());
	}

	if (currentToken == MailcapTokenizer.STRING_TOKEN) {
	    // have a native comand, save the entire mailcap entry
	    //String nativeCommand = tokenizer.getCurrentTokenValue();
	    List v = (List)native_commands.get(mimeType);
	    if (v == null) {
		v = new ArrayList();
		v.add(mailcapEntry);
		native_commands.put(mimeType, v);
	    } else {
		// XXX - check for duplicates?
		v.add(mailcapEntry);
	    }
	}

	//	only have to get the next token if the current one isn't a ';'
	if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) {
	    currentToken = tokenizer.nextToken();
	}

	// look for a ';' which will indicate whether
	// a parameter list is present or not
	if (currentToken == MailcapTokenizer.SEMICOLON_TOKEN) {
	    boolean isFallback = false;
	    do {
		//	eat the ';'

		//	parse the parameter name
		currentToken = tokenizer.nextToken();
		if (currentToken != MailcapTokenizer.STRING_TOKEN) {
		    reportParseError(MailcapTokenizer.STRING_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
		}
		String paramName = tokenizer.getCurrentTokenValue().
						toLowerCase(Locale.ENGLISH);

		//	parse the '=' which separates the name from the value
		currentToken = tokenizer.nextToken();
		if ((currentToken != MailcapTokenizer.EQUALS_TOKEN) &&
		    (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) &&
		    (currentToken != MailcapTokenizer.EOI_TOKEN)) {
		    reportParseError(MailcapTokenizer.EQUALS_TOKEN,
			    MailcapTokenizer.SEMICOLON_TOKEN,
			    MailcapTokenizer.EOI_TOKEN,
			    currentToken, tokenizer.getCurrentTokenValue());
		}

		//	we only have a useful command if it is named
		if (currentToken == MailcapTokenizer.EQUALS_TOKEN) {
		    //	eat it

		    //	parse the parameter value (which is autoquoted)
		    tokenizer.setIsAutoquoting(true);
		    currentToken = tokenizer.nextToken();
		    tokenizer.setIsAutoquoting(false);
		    if (currentToken != MailcapTokenizer.STRING_TOKEN) {
			reportParseError(MailcapTokenizer.STRING_TOKEN,
			currentToken, tokenizer.getCurrentTokenValue());
		    }
		    String paramValue =
				tokenizer.getCurrentTokenValue();

		    // add the class to the list iff it is one we care about
		    if (paramName.startsWith("x-java-")) {
			String commandName = paramName.substring(7);
			//	7 == "x-java-".length

			if (commandName.equals("fallback-entry") &&
			    paramValue.equalsIgnoreCase("true")) {
			    isFallback = true;
			} else {

			    //	setup the class entry list
			    if (LogSupport.isLoggable())
				LogSupport.log("    Command: " + commandName +
						    ", Class: " + paramValue);
			    List classes = (List)commands.get(commandName);
			    if (classes == null) {
				classes = new ArrayList();
				commands.put(commandName, classes);
			    }
			    if (addReverse)
				classes.add(0, paramValue);
			    else
				classes.add(paramValue);
			}
		    }

		    //	set up the next iteration
		    currentToken = tokenizer.nextToken();
		}
	    } while (currentToken == MailcapTokenizer.SEMICOLON_TOKEN);

	    Map masterHash = isFallback ? fallback_hash : type_hash;
	    Map curcommands =
		(Map)masterHash.get(mimeType);
	    if (curcommands == null) {
		masterHash.put(mimeType, commands);
	    } else {
		if (LogSupport.isLoggable())
		    LogSupport.log("Merging commands for type " + mimeType);
		// have to merge current and new commands
		// first, merge list of classes for commands already known
		Iterator cn = curcommands.keySet().iterator();
		while (cn.hasNext()) {
		    String cmdName = (String)cn.next();
		    List ccv = (List)curcommands.get(cmdName);
		    List cv = (List)commands.get(cmdName);
		    if (cv == null)
			continue;
		    // add everything in cv to ccv, if it's not already there
		    Iterator cvn = cv.iterator();
		    while (cvn.hasNext()) {
			String clazz = (String)cvn.next();
			if (!ccv.contains(clazz))
			    if (addReverse)
				ccv.add(0, clazz);
			    else
				ccv.add(clazz);
		    }
		}
		// now, add commands not previously known
		cn = commands.keySet().iterator();
		while (cn.hasNext()) {
		    String cmdName = (String)cn.next();
		    if (curcommands.containsKey(cmdName))
			continue;
		    List cv = (List)commands.get(cmdName);
		    curcommands.put(cmdName, cv);
		}
	    }
	} else if (currentToken != MailcapTokenizer.EOI_TOKEN) {
	    reportParseError(MailcapTokenizer.EOI_TOKEN,
		MailcapTokenizer.SEMICOLON_TOKEN,
		currentToken, tokenizer.getCurrentTokenValue());
	}
     
protected static voidreportParseError(int expectedToken, int actualToken, java.lang.String actualTokenValue)

     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + " token.");
     
protected static voidreportParseError(int expectedToken, int otherExpectedToken, int actualToken, java.lang.String actualTokenValue)

     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + " or a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + " token.");
     
protected static voidreportParseError(int expectedToken, int otherExpectedToken, int anotherExpectedToken, int actualToken, java.lang.String actualTokenValue)

	if (LogSupport.isLoggable())
	    LogSupport.log("PARSE ERROR: " + "Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + ", a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " +
		MailcapTokenizer.nameForToken(anotherExpectedToken) + " token.");
     	throw new MailcapParseException("Encountered a " +
		MailcapTokenizer.nameForToken(actualToken) + " token (" +
		actualTokenValue + ") while expecting a " +
		MailcapTokenizer.nameForToken(expectedToken) + ", a " +
		MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " +
		MailcapTokenizer.nameForToken(anotherExpectedToken) + " token.");