FileDocCategorySizeDatePackage
BodyDescriptor.javaAPI DocAndroid 1.5 API13636Wed May 06 22:42:46 BST 2009org.apache.james.mime4j

BodyDescriptor

public class BodyDescriptor extends Object
Encapsulates the values of the MIME-specific header fields (which starts with Content-).
version
$Id: BodyDescriptor.java,v 1.4 2005/02/11 10:08:37 ntherning Exp $

Fields Summary
private static Log
log
private String
mimeType
private String
boundary
private String
charset
private String
transferEncoding
private Map
parameters
private boolean
contentTypeSet
private boolean
contentTransferEncSet
Constructors Summary
public BodyDescriptor()
Creates a new root BodyDescriptor instance.

    
               
      
        this(null);
    
public BodyDescriptor(BodyDescriptor parent)
Creates a new BodyDescriptor instance.

param
parent the descriptor of the parent or null if this is the root descriptor.

        if (parent != null && parent.isMimeType("multipart/digest")) {
            mimeType = "message/rfc822";
        } else {
            mimeType = "text/plain";
        }
    
Methods Summary
public voidaddField(java.lang.String name, java.lang.String value)
Should be called for each Content- header field of a MIME message or part.

param
name the field name.
param
value the field value.

        
        name = name.trim().toLowerCase();
        
        if (name.equals("content-transfer-encoding") && !contentTransferEncSet) {
            contentTransferEncSet = true;
            
            value = value.trim().toLowerCase();
            if (value.length() > 0) {
                transferEncoding = value;
            }
            
        } else if (name.equals("content-type") && !contentTypeSet) {
            contentTypeSet = true;
            
            value = value.trim();
            
            /*
             * Unfold Content-Type value
             */
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < value.length(); i++) {
                char c = value.charAt(i);
                if (c == '\r" || c == '\n") {
                    continue;
                }
                sb.append(c);
            }
            
            Map params = getHeaderParams(sb.toString());
            
            String main = (String) params.get("");
            if (main != null) {
                main = main.toLowerCase().trim();
                int index = main.indexOf('/");
                boolean valid = false;
                if (index != -1) {
                    String type = main.substring(0, index).trim();
                    String subtype = main.substring(index + 1).trim();
                    if (type.length() > 0 && subtype.length() > 0) {
                        main = type + "/" + subtype;
                        valid = true;
                    }
                }
                
                if (!valid) {
                    main = null;
                }
            }
            String b = (String) params.get("boundary");
            
            if (main != null 
                    && ((main.startsWith("multipart/") && b != null) 
                            || !main.startsWith("multipart/"))) {
                
                mimeType = main;
            }
            
            if (isMultipart()) {
                boundary = b;
            }
            
            String c = (String) params.get("charset");
            if (c != null) {
                c = c.trim();
                if (c.length() > 0) {
                    charset = c.toLowerCase();
                }
            }
            
            /*
             * Add all other parameters to parameters.
             */
            parameters.putAll(params);
            parameters.remove("");
            parameters.remove("boundary");
            parameters.remove("charset");
        }
    
public java.lang.StringgetBoundary()
Return the boundary

return
boundary

        return boundary;
    
public java.lang.StringgetCharset()
Return the charset

return
charset

        return charset;
    
private java.util.MapgetHeaderParams(java.lang.String headerValue)

        Map result = new HashMap();

        // split main value and parameters
        String main;
        String rest;
        if (headerValue.indexOf(";") == -1) {
            main = headerValue;
            rest = null;
        } else {
            main = headerValue.substring(0, headerValue.indexOf(";"));
            rest = headerValue.substring(main.length() + 1);
        }

        result.put("", main);
        if (rest != null) {
            char[] chars = rest.toCharArray();
            StringBuffer paramName = new StringBuffer();
            StringBuffer paramValue = new StringBuffer();

            final byte READY_FOR_NAME = 0;
            final byte IN_NAME = 1;
            final byte READY_FOR_VALUE = 2;
            final byte IN_VALUE = 3;
            final byte IN_QUOTED_VALUE = 4;
            final byte VALUE_DONE = 5;
            final byte ERROR = 99;

            byte state = READY_FOR_NAME;
            boolean escaped = false;
            for (int i = 0; i < chars.length; i++) {
                char c = chars[i];

                switch (state) {
                    case ERROR:
                        if (c == ';")
                            state = READY_FOR_NAME;
                        break;

                    case READY_FOR_NAME:
                        if (c == '=") {
                            log.error("Expected header param name, got '='");
                            state = ERROR;
                            break;
                        }

                        paramName = new StringBuffer();
                        paramValue = new StringBuffer();

                        state = IN_NAME;
                        // fall-through

                    case IN_NAME:
                        if (c == '=") {
                            if (paramName.length() == 0)
                                state = ERROR;
                            else
                                state = READY_FOR_VALUE;
                            break;
                        }

                        // not '='... just add to name
                        paramName.append(c);
                        break;

                    case READY_FOR_VALUE:
                        boolean fallThrough = false;
                        switch (c) {
                            case ' ":
                            case '\t":
                                break;  // ignore spaces, especially before '"'

                            case '"":
                                state = IN_QUOTED_VALUE;
                                break;

                            default:
                                state = IN_VALUE;
                                fallThrough = true;
                                break;
                        }
                        if (!fallThrough)
                            break;

                        // fall-through

                    case IN_VALUE:
                        fallThrough = false;
                        switch (c) {
                            case ';":
                            case ' ":
                            case '\t":
                                result.put(
                                   paramName.toString().trim().toLowerCase(),
                                   paramValue.toString().trim());
                                state = VALUE_DONE;
                                fallThrough = true;
                                break;
                            default:
                                paramValue.append(c);
                                break;
                        }
                        if (!fallThrough)
                            break;

                    case VALUE_DONE:
                        switch (c) {
                            case ';":
                                state = READY_FOR_NAME;
                                break;

                            case ' ":
                            case '\t":
                                break;

                            default:
                                state = ERROR;
                                break;
                        }
                        break;
                        
                    case IN_QUOTED_VALUE:
                        switch (c) {
                            case '"":
                                if (!escaped) {
                                    // don't trim quoted strings; the spaces could be intentional.
                                    result.put(
                                            paramName.toString().trim().toLowerCase(),
                                            paramValue.toString());
                                    state = VALUE_DONE;
                                } else {
                                    escaped = false;
                                    paramValue.append(c);                                    
                                }
                                break;
                                
                            case '\\":
                                if (escaped) {
                                    paramValue.append('\\");
                                }
                                escaped = !escaped;
                                break;

                            default:
                                if (escaped) {
                                    paramValue.append('\\");
                                }
                                escaped = false;
                                paramValue.append(c);
                                break;
                        }
                        break;

                }
            }

            // done looping.  check if anything is left over.
            if (state == IN_VALUE) {
                result.put(
                        paramName.toString().trim().toLowerCase(),
                        paramValue.toString().trim());
            }
        }

        return result;
    
public java.lang.StringgetMimeType()
Return the MimeType

return
mimeType

        return mimeType;
    
public java.util.MapgetParameters()
Return all parameters for the BodyDescriptor

return
parameters

        return parameters;
    
public java.lang.StringgetTransferEncoding()
Return the TransferEncoding

return
transferEncoding

        return transferEncoding;
    
public booleanisBase64Encoded()
Return true if it's base64 encoded

return

        return "base64".equals(transferEncoding);
    
public booleanisMessage()
Return true if the BodyDescriptor belongs to a message

return

        return mimeType.equals("message/rfc822");
    
public booleanisMimeType(java.lang.String mimeType)

        return this.mimeType.equals(mimeType.toLowerCase());
    
public booleanisMultipart()
Retrun true if the BodyDescripotro belogns to a multipart

return

        return mimeType.startsWith("multipart/");
    
public booleanisQuotedPrintableEncoded()
Return true if it's quoted-printable

return

        return "quoted-printable".equals(transferEncoding);
    
public java.lang.StringtoString()

        return mimeType;