| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.geronimo.javamail.store.imap; |
| |
| import java.io.InputStream; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Enumeration; |
| |
| import javax.activation.DataHandler; |
| import javax.mail.IllegalWriteException; |
| import javax.mail.MessagingException; |
| import javax.mail.Multipart; |
| import javax.mail.internet.MimeBodyPart; |
| import javax.mail.internet.MimeUtility; |
| |
| import org.apache.geronimo.javamail.store.imap.connection.IMAPBodyStructure; |
| import org.apache.geronimo.javamail.store.imap.connection.IMAPConnection; |
| import org.apache.geronimo.mail.util.SessionUtil; |
| |
| |
| public class IMAPMimeBodyPart extends MimeBodyPart { |
| // the message we're part of |
| protected IMAPMessage message; |
| // the retrieved BODYSTRUCTURE information for this part. |
| protected IMAPBodyStructure bodyStructure; |
| // the section identifier. This will be in a format such as 1.2.3, which |
| // would refer to the "third part contained in the second part of the first part"... |
| // got all that? There will be a quiz at the end of class :-) |
| protected String section; |
| // flag to indicate whether the body part headers have been loaded. |
| boolean headersLoaded = false; |
| |
| /** |
| * Create an instance of a MimeBodyPart within an |
| * IMAP message. |
| * |
| * @param message The parent Message instance containing this part. |
| * @param bodyStructure |
| * The IMAPBodyStructure information describing the part. |
| * @param section The numeric section identifier string for this part. |
| * This is a hierarchical set of numbers describing |
| * how to navigate to the message part on the IMAP |
| * server. For example, "2.1.3" would be the third |
| * subpart of the first subpart of the second main |
| * message part. |
| */ |
| public IMAPMimeBodyPart(IMAPMessage message, IMAPBodyStructure bodyStructure, String section) { |
| super(); |
| this.message = message; |
| this.bodyStructure = bodyStructure; |
| this.section = section; |
| } |
| |
| |
| /** |
| * Get the size of the message part. |
| * |
| * @return The size information returned in the IMAP body structure. |
| * @exception MessagingException |
| */ |
| public int getSize() throws MessagingException { |
| return bodyStructure.bodySize; |
| } |
| |
| /** |
| * Get the estimated line count for the body part. |
| * |
| * @return The line count information returned by the IMAP |
| * server. |
| * @exception MessagingException |
| */ |
| public int getLineCount() throws MessagingException { |
| return bodyStructure.lines; |
| } |
| |
| /** |
| * Get the content type for the body part. |
| * |
| * @return The mimetype for the body part, in string format. |
| * @exception MessagingException |
| */ |
| public String getContentType() throws MessagingException { |
| return bodyStructure.mimeType.toString(); |
| } |
| |
| /** |
| * Test if the body part is of a particular MIME type. |
| * |
| * @param type The string MIME-type name. A wild card * can be |
| * specified for the subpart type. |
| * |
| * @return true if the body part matches the give MIME-type. |
| * @exception MessagingException |
| */ |
| public boolean isMimeType(String type) throws MessagingException { |
| return bodyStructure.mimeType.match(type); |
| } |
| |
| /** |
| * Retrieve the disposition information about this |
| * body part. |
| * |
| * @return The disposition information, as a string value. |
| * @exception MessagingException |
| */ |
| public String getDisposition() throws MessagingException { |
| return bodyStructure.disposition.getDisposition(); |
| } |
| |
| /** |
| * Set the disposition information. The IMAP message |
| * is read-only, so this is an error. |
| * |
| * @param disposition |
| * The disposition string. |
| * |
| * @exception MessagingException |
| */ |
| public void setDisposition(String disposition) throws MessagingException { |
| throw new IllegalWriteException("IMAP message parts are read-only"); |
| } |
| |
| public String getEncoding() throws MessagingException { |
| return bodyStructure.transferEncoding; |
| } |
| |
| public String getContentID() throws MessagingException { |
| return bodyStructure.contentID; |
| } |
| |
| public void setContentID(String id) throws MessagingException { |
| throw new IllegalWriteException("IMAP message parts are read-only"); |
| } |
| |
| public String getContentMD5() throws MessagingException { |
| return bodyStructure.md5Hash; |
| } |
| |
| public void setContentMD5(String id) throws MessagingException { |
| throw new IllegalWriteException("IMAP message parts are read-only"); |
| } |
| |
| public String getDescription() throws MessagingException { |
| String description = bodyStructure.contentDescription; |
| if (description != null) { |
| try { |
| // this could be both folded and encoded. Return this to usable form. |
| return MimeUtility.decodeText(MimeUtility.unfold(description)); |
| } catch (UnsupportedEncodingException e) { |
| // ignore |
| } |
| } |
| // return the raw version for any errors (this might be null also) |
| return description; |
| } |
| |
| public void setDescription(String d, String charset) throws MessagingException { |
| throw new IllegalWriteException("IMAP message parts are read-only"); |
| } |
| |
| public String getFileName() throws MessagingException { |
| String filename = bodyStructure.disposition.getParameter("filename"); |
| if (filename == null) { |
| filename = bodyStructure.mimeType.getParameter("name"); |
| } |
| |
| // if we have a name, we might need to decode this if an additional property is set. |
| if (filename != null && SessionUtil.getBooleanProperty(MIME_DECODEFILENAME, false)) { |
| try { |
| filename = MimeUtility.decodeText(filename); |
| } catch (UnsupportedEncodingException e) { |
| throw new MessagingException("Unable to decode filename", e); |
| } |
| } |
| |
| return filename; |
| } |
| |
| public void setFileName(String name) throws MessagingException { |
| throw new IllegalWriteException("IMAP message parts are read-only"); |
| } |
| |
| protected InputStream getContentStream() throws MessagingException { |
| |
| // no content loaded yet? |
| if (content == null) { |
| // make sure we're still valid |
| message.checkValidity(); |
| // make sure the content is fully loaded |
| loadContent(); |
| } |
| |
| // allow the super class to handle creating it from the loaded content. |
| return super.getContentStream(); |
| } |
| |
| |
| /** |
| * Create the DataHandler object for this message. |
| * |
| * @return The DataHandler object that processes the content set for this |
| * message. |
| * @exception MessagingException |
| */ |
| public synchronized DataHandler getDataHandler() throws MessagingException { |
| if (dh == null) { |
| // are we working with a multipart message here? |
| if (bodyStructure.isMultipart()) { |
| dh = new DataHandler(new IMAPMultipartDataSource(message, this, section, bodyStructure)); |
| return dh; |
| } |
| else if (bodyStructure.isAttachedMessage()) { |
| dh = new DataHandler(new IMAPAttachedMessage(message, section, bodyStructure.nestedEnvelope, |
| bodyStructure.nestedBody), bodyStructure.mimeType.toString()); |
| return dh; |
| } |
| } |
| |
| // single part messages get handled the normal way. |
| return super.getDataHandler(); |
| } |
| |
| public void setDataHandler(DataHandler content) throws MessagingException { |
| throw new IllegalWriteException("IMAP body parts are read-only"); |
| } |
| |
| public void setContent(Object o, String type) throws MessagingException { |
| throw new IllegalWriteException("IMAP body parts are read-only"); |
| } |
| |
| public void setContent(Multipart mp) throws MessagingException { |
| throw new IllegalWriteException("IMAP body parts are read-only"); |
| } |
| |
| |
| /****************************************************************** |
| * Following is a set of methods that deal with headers |
| * These methods are just overrides on the superclass methods to |
| * allow lazy loading of the header information. |
| ********************************************************************/ |
| |
| public String[] getHeader(String name) throws MessagingException { |
| loadHeaders(); |
| return headers.getHeader(name); |
| } |
| |
| public String getHeader(String name, String delimiter) throws MessagingException { |
| loadHeaders(); |
| return headers.getHeader(name, delimiter); |
| } |
| |
| public Enumeration getAllHeaders() throws MessagingException { |
| loadHeaders(); |
| return headers.getAllHeaders(); |
| } |
| |
| public Enumeration getMatchingHeaders(String[] names) throws MessagingException { |
| loadHeaders(); |
| return headers.getMatchingHeaders(names); |
| } |
| |
| public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException { |
| loadHeaders(); |
| return headers.getNonMatchingHeaders(names); |
| } |
| |
| public Enumeration getAllHeaderLines() throws MessagingException { |
| loadHeaders(); |
| return headers.getAllHeaderLines(); |
| } |
| |
| public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException { |
| loadHeaders(); |
| return headers.getMatchingHeaderLines(names); |
| } |
| |
| public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException { |
| loadHeaders(); |
| return headers.getNonMatchingHeaderLines(names); |
| } |
| |
| // the following are overrides for header modification methods. These messages are read only, |
| // so the headers cannot be modified. |
| public void addHeader(String name, String value) throws MessagingException { |
| throw new IllegalWriteException("IMAP messages are read-only"); |
| } |
| |
| public void setHeader(String name, String value) throws MessagingException { |
| throw new IllegalWriteException("IMAP messages are read-only"); |
| } |
| |
| |
| public void removeHeader(String name) throws MessagingException { |
| throw new IllegalWriteException("IMAP messages are read-only"); |
| } |
| |
| public void addHeaderLine(String line) throws MessagingException { |
| throw new IllegalWriteException("IMAP messages are read-only"); |
| } |
| |
| |
| /** |
| * Load the mime part headers into this body part. |
| * |
| * @exception MessagingException |
| */ |
| protected synchronized void loadHeaders() throws MessagingException { |
| // have them already? Super.. |
| if (headers != null) { |
| return; |
| } |
| |
| IMAPConnection connection = message.getConnection(); |
| try { |
| // this asks for the MIME subsection of the given section piece. |
| headers = connection.fetchHeaders(message.getSequenceNumber(), section); |
| } finally { |
| message.releaseConnection(connection); |
| } |
| |
| } |
| |
| |
| /** |
| * Load the message content into the BodyPart object. |
| * |
| * @exception MessagingException |
| */ |
| protected void loadContent() throws MessagingException { |
| // if we've loaded this already, just return |
| if (content != null) { |
| return; |
| } |
| |
| IMAPConnection connection = message.getConnection(); |
| try { |
| // load the content from the server. |
| content = connection.fetchContent(message.getSequenceNumber(), section); |
| } finally { |
| message.releaseConnection(connection); |
| } |
| } |
| } |
| |