⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mimemessage.java

📁 用于开发mms应用的Java库
💻 JAVA
字号:
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the Tambur MMS library.
 *
 * The Initial Developer of the Original Code is FlyerOne Ltd.
 * Portions created by the Initial Developer are Copyright (C) 2005
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * 	Anders Lindh <alindh@flyerone.com>
 *
 * ***** END LICENSE BLOCK ***** */

package net.tambur.mms;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

import org.apache.log4j.Logger;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * This class implements multipart MIME (RFC 1521, RFC 2045) message parsing and encoding. 
 * Different parts of the message can thus be easily accessed, and messages can be created.
 * <p>
 * Compability is still limited; the intended use is for Multimedia Messages, and this class 
 * provides a light-weight ground for the MMMessage implementation. 
 * <p>
 * 
 * 
 * @author Anders Lindh
 * @copyright Copyright FlyerOne Ltd 2005
 * @version $Revision: 1.1.1.1 $ $Date: 2005/04/14 09:04:10 $
 */
public class MimeMessage implements Serializable {

	/**
	 * logger 
	 */
	protected transient Logger log = Logger.getLogger(this.getClass());

 	private static byte[] CRLF = {0x0D, 0x0A};

	/**
	 * parts in the message
	 */
	protected ArrayList parts;
	
	/**
	 * Message headers (attributes)
	 */
	protected ArrayList headerNames;
	protected ArrayList headerValues;
	
	/**
	 * Content type of message
	 */
	protected String contentType;

	/**
	 * boundary
	 */
	protected String boundary = null;

	/** 
	 * representation of parts
	 */
	public class MimePart implements Serializable {
		private byte[] content;
		
		public ArrayList headerNames;
		public ArrayList headerValues;
		protected String contentType;
		
		public MimePart(String contenttype, byte[] content, boolean base64, ArrayList names, ArrayList values) {
			this.headerNames = names;
			this.headerValues = values;
			
			if (this.headerNames == null) this.headerNames = new ArrayList();
			if (this.headerValues == null) this.headerValues = new ArrayList();			
			this.content = content;
			
			this.contentType = contenttype;
			
			if (base64) this.setAttribute("Content-Transfer-Encoding", "base64");
		}
		
		public void setAttribute(String name, String value) { 
			int idx = headerNames.indexOf(name);
		
			if (idx != -1) {
 				headerNames.set(idx, name);
				headerValues.set(idx, value);
			} else {
	 			headerNames.add(name);
				headerValues.add(value);			
			} 
		}
		
		public String getAttribute(String name) { 
			int idx = headerNames.indexOf(name);
			if (idx == -1) {
				// try to find (case insensitive)
				ListIterator i = headerNames.listIterator();
				idx = 0;
				while (i.hasNext()) {
					String n = (String) i.next();
					if 	(name.equalsIgnoreCase(n)) return (String) headerValues.get(idx); 
					idx++;
				}				
			} else return (String) headerValues.get(idx); 
			return null;
		}
		
		public ArrayList getAttributeNames() { return this.headerNames; }
		public ArrayList getAttributeValues() { return this.headerValues; }
		
		public String getContentType() { return contentType; }
		public void setContentType(String s) { contentType = s; }
		
		public void removeAttribute(String name) { 
			int idx = headerNames.indexOf(name);
			if (idx == -1) return;
				
			headerNames.remove(idx);
			headerValues.remove(idx);
		}
		
		public byte[] getContent() { return content; }
	}	
	
	/**
	 * Constructor for MimeMessage.
	 */
	public MimeMessage() {
		parts = new ArrayList();	
			
		headerValues = new ArrayList();
		headerNames = new ArrayList();
			
		// generate a boundary for this message (25 chars)
        char[] rnd = new char[25];
        for (int a = 0; a < rnd.length; a++) {
            long l = Math.round(Math.random() * 25); // 25 alphanumeric chars 
            
            long coin = Math.round(Math.random()); // some variation            
            
            char base = 'A';
            if (coin == 1) base = 'a';
            
            rnd[a] = (char) (base + l);
        }
        
        boundary = new String(rnd); 
    }
    
    /**
     * create message from string
     */
    public MimeMessage(String message) {
    	parts = new ArrayList();
    	
    	StringBuffer tmp = new StringBuffer(message);
    	
    	// clean up headers 
		int i = 0;

		while ((i = message.indexOf("\r\r\n")) != -1) {
			tmp.replace(i, i+3, "\r\n");
			message = tmp.toString();
		}
		
		while ((i = message.indexOf("\r\n\t")) != -1) {
			tmp.replace(i, i+3, " ");
			message = tmp.toString();
		}
    	
    	StringReader sr = new StringReader(message);
    	BufferedReader br = new BufferedReader(sr);
    	
		String line = null;
		
		ArrayList headerNames = new ArrayList();
		ArrayList headerValues = new ArrayList();
		
		try {
			while ((line = br.readLine()) != null) {
	
				if (line.equals("")) break;
				if (line.indexOf(':') != -1) {
					String name = line.substring(0, line.indexOf(':')).trim();
					String value = line.substring(line.indexOf(':')+1, line.length()).trim();
					
					// extract boundary if this is our content type
					if (name.equalsIgnoreCase("Content-Type")) {
						int s = value.indexOf("boundary");						
						if (s != -1) {
							s += 9;
							boundary = value.substring(s, value.length());
							if (boundary.indexOf(';') != -1)
								boundary = boundary.substring(0, boundary.indexOf(';'));
							if (boundary.startsWith("\""))
								boundary = boundary.substring(1, boundary.length()-1);
							//while (boundary.charAt(0) == '-')
							//	boundary = boundary.substring(1, boundary.length());							
						} else boundary = null;
						
						setContentType(value.substring(0, value.indexOf(" ")));
						continue;
					}
			
					headerNames.add(name);
					headerValues.add(value);
				}
			}    	
		} catch (Exception e) {
			log.error(e);
			e.printStackTrace();
		}
		
		this.headerValues = headerValues;
		this.headerNames = headerNames;
		
		if (boundary == null) {
			log.debug("No parts in mime message");
			return; 
		} // no parts
		
		// start extracting parts
		try {
			while ((line = br.readLine()) != null) {
				if (line.startsWith("--" + boundary)) continue;
				if (line.equals("")) continue;
					
				ArrayList hNames = new ArrayList();
				ArrayList hValues = new ArrayList();					
				boolean base64 = false;
					
				//if (line.endsWith("--")) break; // end-of-content

				String ct = null;
					
				// extract headers
				while (true) {
					if ((line == null) || (line.equals(""))) break;
					
					if (line.indexOf(':') != -1) {
						String name = line.substring(0, line.indexOf(':')).trim();
						String value = line.substring(line.indexOf(':')+1, line.length()).trim();
							
						if (name.equalsIgnoreCase("Content-Type")) ct = value; else
						if (name.equalsIgnoreCase("Content-Transfer-Encoding")) {
							if (value.equalsIgnoreCase("base64")) base64 = true;
						} else {
							hNames.add(name);
							hValues.add(value); 
						}
					}
					
					line = br.readLine();
						
				}

				if (ct == null) {
					// System.out.println("Skipping part without content-type");
					break;
				}			
							
				// extract content
				String content = "";
				while ((line = br.readLine()) != null) {
					if (line.equals("")) break;
					if (line.startsWith("--" + boundary)) break;
					content += line;
				}	
					
				byte data[] = content.getBytes();
					
				if (base64 == true) {
					BASE64Decoder b64 = new BASE64Decoder();
					data = b64.decodeBuffer(content);
				}
					
				addPart(ct, data, base64, hNames, hValues);
			}
		} catch (Exception e) {
			log.error(e);
			e.printStackTrace();
		}
			
		    	
    }

	public String getContentType() { return contentType; }
	public void setContentType(String s) { contentType = s; }

	/**
	 * add a part to the message
	 */
	public void addPart(String contenttype, byte[] content, boolean base64, ArrayList names, ArrayList values) {
		MimePart part = new MimePart(contenttype, content, base64, names, values);
		parts.add(part);
	}	
	
	public void addPart(MimePart part) {
		parts.add(part);
	}
	
	/**
	 * get part
	 */
	public MimePart getPart(int idx) {
		return (MimePart) parts.get(idx);
	}
	
	/**
	 * Remove a part
	 */
	public void removePart(int idx) {
		parts.remove(idx);
	}

	/**
	 * get part
	 */
	public int getPartCount() {
		return parts.size();
	}
	
	/** 
	 * add a header
	 */
	public void setAttribute(String name, String value) {
		int idx = headerNames.indexOf(name);
		
		if (idx != -1) {
 			headerNames.set(idx, name);
			headerValues.set(idx, value);
		} else {
 			headerNames.add(name);
			headerValues.add(value);			
		}
	}
	
	/**
	 * get a header
	 */
	public String getAttribute(String name) {
		int idx = headerNames.indexOf(name);
		if (idx != -1)
			return (String) headerValues.get(idx); else
			return null;
	}
	
	/**
	 * get iteration over all headers
	 */
	public ListIterator getAttributes() {
		return headerNames.listIterator();
	}
	
	/**
	 * remove named header
	 */
	public void removeAttribute(String name) {
		int idx = headerNames.indexOf(name);
		if (idx == -1) return;
				
		headerNames.remove(idx);
		headerValues.remove(idx);
	}
	
	/**
	 * serialize message to a string
	 * 
	 * @return String containing MIME compatible representation of message, if
	 * message contains no parts, null is returned
	 */
	public String toString() {
		byte[] b = getBytes();
		if (b == null) return null;
		return new String(b);
	}
	
	/**
	 * Return boundary used in creating a String representation
	 */
	public String getBoundary() {
		return boundary;
	}
	
	public byte[] getBytes() {
		return getBytes(true);
	}
	
	/**
	 * return a byte array representation of this object
	 */
	public byte[] getBytes(boolean includeHeaders) {		
		ByteArrayOutputStream res = new ByteArrayOutputStream();
		
		ArrayList mimeheaderValues = new ArrayList();
		ArrayList mimeheaderNames = new ArrayList();		
		
		if (getAttribute("MIME-Version") == null) {
			mimeheaderNames.add("MIME-Version");
			mimeheaderValues.add("1.0");
		}
		
		String ct = null; // getContentType();
			
		if ((ct != null) && (ct.indexOf(" ") != -1)) { // insert boundary
			// ct = "multipart/mixed; " + ct.substring(ct.indexOf(" ")+1, ct.length());			
			ct.trim();
			// squeese the rest of the parameters, and replace ":" with "="
			while (ct.indexOf(":") != -1)
				ct = ct.substring(0, ct.indexOf(":")) + "=" + ct.substring(ct.indexOf(":")+1, ct.length()).trim();
		}	

		if (ct != null) ct = ct + "; boundary=\"" + boundary + "\"; "; else
			ct = "multipart/mixed; boundary=\"" + boundary + "\"";
						
		try {	
			if (includeHeaders) {					
				serializeAttributes(res, mimeheaderNames, mimeheaderValues);					
				serializeAttributes(res, headerNames, headerValues);				
				res.write(("Content-Type: " + ct).getBytes());
				res.write(CRLF);
				res.write(CRLF);
			}			
			
			if (!parts.isEmpty()) {
				Iterator i = parts.iterator();
				while (i.hasNext()) {
					MimePart part = (MimePart) i.next();
					byte[] c = part.content;

					String cte = part.getAttribute("Content-Transfer-Encoding");
					boolean base64 = false;
					
					if ((cte != null) && (cte.equalsIgnoreCase("base64"))) base64 = true;
					
					//if (base64 == false) { // try to guess
						//if (part.getContentType().startsWith("image/")) base64 = true; else
						//if (part.getContentType().startsWith("application/octet")) base64 = true; else
						//if (part.getContentType().startsWith("audio/")) base64 = true;
					//}
					
					base64 = true; // just to be safe
					
					if (base64) {		
						if (cte == null)
							part.setAttribute("Content-Transfer-Encoding", "base64");
							
			            BASE64Encoder b64 = new BASE64Encoder();
		                c = b64.encodeBuffer(part.content).getBytes();
					}
			
					res.write(("--" + boundary).getBytes());
					res.write(CRLF);
					
					res.write(("Content-Type: " + part.getContentType()).getBytes("iso-8859-1"));
					res.write(CRLF);
					serializeAttributes(res, part.getAttributeNames(), part.getAttributeValues());
					res.write(CRLF);

					if (c != null) res.write(c);
					res.write(CRLF);
				}
		
				res.write(("--" + boundary + "--").getBytes()); 
				res.write(CRLF);
			}
		} catch (Exception e) {
			log.error("MimeMessage.getBytes(): " + e);
			e.printStackTrace();
			return null;
		}	
					
		return res.toByteArray();		
	}
	
	/**
	 * create a e-mail compatible mime message out of this message
	 */
	public javax.mail.internet.MimeMessage toMimeMessage(javax.mail.Session session) {
		//javax.mail.internet.MimeMessage email = new javax.mail.internet.MimeMessage(session);
             	
        try {
			byte[] b = getBytes();
			if (b == null) return null;
			
			ByteArrayInputStream bais = new ByteArrayInputStream(b);
		
			javax.mail.internet.MimeMessage email = new javax.mail.internet.MimeMessage(session, bais);
			return email;
        } catch (Exception e) {
        	log.error("toMimeMessage: " + e);
        }
        
        return null; 
	}	

	/**
	 * serialize attributes to given OutputStream
	 */	
	protected void serializeAttributes(ByteArrayOutputStream res, ArrayList names, ArrayList values) throws Exception{
		if ((names == null) || (names.isEmpty()) || (res == null)) return;
		if ((values == null) || (values.isEmpty())) return;

		Iterator i = names.iterator();

		if (i == null) return;
		int idx = 0;
		while (i.hasNext()) {
			
			String name = (String) i.next();
			String val = (String) values.get(idx++);
			
			if ((name == null) || (val == null)) continue;

			res.write((name).getBytes());			
			res.write((": ").getBytes());	
			res.write((val).getBytes());					
			res.write(CRLF);
		}
	}
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -