1 /**
2 *
3 * Copyright 2003-2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package javax.mail.internet;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.io.PrintStream;
24 import javax.activation.DataSource;
25 import javax.mail.BodyPart;
26 import javax.mail.MessagingException;
27 import javax.mail.Multipart;
28 import javax.mail.MultipartDataSource;
29
30 /**
31 * @version $Rev: 154541 $ $Date: 2005-02-20 10:01:49 -0800 (Sun, 20 Feb 2005) $
32 */
33 public class MimeMultipart extends Multipart {
34 /**
35 * DataSource that provides our InputStream.
36 */
37 protected DataSource ds;
38 /**
39 * Indicates if the data has been parsed.
40 */
41 protected boolean parsed;
42
43 private transient ContentType type;
44
45 /**
46 * Create an empty MimeMultipart with content type "multipart/mixed"
47 */
48 public MimeMultipart() {
49 this("mixed");
50 }
51
52 /**
53 * Create an empty MimeMultipart with the subtype supplied.
54 *
55 * @param subtype the subtype
56 */
57 public MimeMultipart(String subtype) {
58 type = new ContentType("multipart", subtype, null);
59 type.setParameter("boundary", getBoundary());
60 contentType = type.toString();
61 }
62
63 /**
64 * Create a MimeMultipart from the supplied DataSource.
65 *
66 * @param dataSource the DataSource to use
67 * @throws MessagingException
68 */
69 public MimeMultipart(DataSource dataSource) throws MessagingException {
70 ds = dataSource;
71 if (dataSource instanceof MultipartDataSource) {
72 super.setMultipartDataSource((MultipartDataSource) dataSource);
73 parsed = true;
74 } else {
75 type = new ContentType(ds.getContentType());
76 contentType = type.toString();
77 parsed = false;
78 }
79 }
80
81 public void setSubType(String subtype) throws MessagingException {
82 type.setSubType(subtype);
83 contentType = type.toString();
84 }
85
86 public int getCount() throws MessagingException {
87 parse();
88 return super.getCount();
89 }
90
91 public synchronized BodyPart getBodyPart(int part) throws MessagingException {
92 parse();
93 return super.getBodyPart(part);
94 }
95
96 public BodyPart getBodyPart(String cid) throws MessagingException {
97 parse();
98 for (int i = 0; i < parts.size(); i++) {
99 MimeBodyPart bodyPart = (MimeBodyPart) parts.get(i);
100 if (cid.equals(bodyPart.getContentID())) {
101 return bodyPart;
102 }
103 }
104 return null;
105 }
106
107 protected void updateHeaders() throws MessagingException {
108 parse();
109 for (int i = 0; i < parts.size(); i++) {
110 MimeBodyPart bodyPart = (MimeBodyPart) parts.get(i);
111 bodyPart.updateHeaders();
112 }
113 }
114
115 private static byte[] dash = { '-', '-' };
116 private static byte[] crlf = { 13, 10 };
117
118 public void writeTo(OutputStream out) throws IOException, MessagingException {
119 parse();
120 String boundary = type.getParameter("boundary");
121 byte[] bytes = boundary.getBytes();
122 for (int i = 0; i < parts.size(); i++) {
123 BodyPart bodyPart = (BodyPart) parts.get(i);
124 out.write(dash);
125 out.write(bytes);
126 out.write(crlf);
127 bodyPart.writeTo(out);
128 out.write(crlf);
129 }
130 out.write(dash);
131 out.write(bytes);
132 out.write(crlf);
133 out.flush();
134 }
135
136 protected void parse() throws MessagingException {
137 if (parsed) {
138 return;
139 }
140 parsed = true;
141 }
142
143 protected InternetHeaders createInternetHeaders(InputStream in) throws MessagingException {
144 return new InternetHeaders(in);
145 }
146
147 protected MimeBodyPart createMimeBodyPart(InternetHeaders headers, byte[] data) throws MessagingException {
148 return new MimeBodyPart(headers, data);
149 }
150
151 protected MimeBodyPart createMimeBodyPart(InputStream in) throws MessagingException {
152 return new MimeBodyPart(in);
153 }
154
155 private static int part;
156
157 private synchronized static String getBoundary() {
158 int i;
159 synchronized(MimeMultipart.class) {
160 i = part++;
161 }
162 StringBuffer buf = new StringBuffer(64);
163 buf.append("----=_Part_").append(i).append('.').append(System.currentTimeMillis());
164 return buf.toString();
165 }
166 }