]> git.argeo.org Git - gpl/argeo-slc.git/blob - ext/javax.mail.mbox/src/com/sun/mail/mbox/SunV3Multipart.java
Make logging synchronous during native image build
[gpl/argeo-slc.git] / ext / javax.mail.mbox / src / com / sun / mail / mbox / SunV3Multipart.java
1 /*
2 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0, which is available at
6 * http://www.eclipse.org/legal/epl-2.0.
7 *
8 * This Source Code may also be made available under the following Secondary
9 * Licenses when the conditions for such availability set forth in the
10 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11 * version 2 with the GNU Classpath Exception, which is available at
12 * https://www.gnu.org/software/classpath/license.html.
13 *
14 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15 */
16
17 package com.sun.mail.mbox;
18
19 import javax.mail.*;
20 import javax.mail.internet.*;
21 import javax.activation.*;
22 import java.util.*;
23 import java.io.*;
24 import java.nio.charset.StandardCharsets;
25 import com.sun.mail.util.LineInputStream;
26
27 /**
28 * The SunV3Multipart class is an implementation of the abstract Multipart
29 * class that uses SunV3 conventions for the multipart data. <p>
30 *
31 * @author Bill Shannon
32 */
33
34 public class SunV3Multipart extends MimeMultipart {
35 private boolean parsing;
36
37 /**
38 * Constructs a SunV3Multipart object and its bodyparts from the
39 * given DataSource. <p>
40 *
41 * @param ds DataSource, can be a MultipartDataSource
42 */
43 public SunV3Multipart(DataSource ds) throws MessagingException {
44 super(ds);
45 }
46
47 /**
48 * Set the subtype. Throws MethodNotSupportedException.
49 *
50 * @param subtype Subtype
51 */
52 public void setSubType(String subtype) throws MessagingException {
53 throw new MethodNotSupportedException(
54 "can't change SunV3Multipart subtype");
55 }
56
57 /**
58 * Get the BodyPart referred to by the given ContentID (CID).
59 * Throws MethodNotSupportException.
60 */
61 public synchronized BodyPart getBodyPart(String CID)
62 throws MessagingException {
63 throw new MethodNotSupportedException(
64 "SunV3Multipart doesn't support Content-ID");
65 }
66
67 /**
68 * Update headers. Throws MethodNotSupportException.
69 */
70 protected void updateHeaders() throws MessagingException {
71 throw new MethodNotSupportedException("SunV3Multipart not writable");
72 }
73
74 /**
75 * Iterates through all the parts and outputs each SunV3 part
76 * separated by a boundary.
77 */
78 public void writeTo(OutputStream os)
79 throws IOException, MessagingException {
80 throw new MethodNotSupportedException(
81 "SunV3Multipart writeTo not supported");
82 }
83
84 private static final String boundary = "----------";
85
86 /*
87 * Parse the contents of this multipart message and create the
88 * child body parts.
89 */
90 protected synchronized void parse() throws MessagingException {
91 /*
92 * If the data has already been parsed, or we're in the middle of
93 * parsing it, there's nothing to do. The latter will occur when
94 * we call addBodyPart, which will call parse again. We really
95 * want to be able to call super.super.addBodyPart.
96 */
97 if (parsed || parsing)
98 return;
99
100 InputStream in = null;
101
102 try {
103 in = ds.getInputStream();
104 if (!(in instanceof ByteArrayInputStream) &&
105 !(in instanceof BufferedInputStream))
106 in = new BufferedInputStream(in);
107 } catch (IOException ex) {
108 throw new MessagingException("No inputstream from datasource");
109 } catch (RuntimeException ex) {
110 throw new MessagingException("No inputstream from datasource");
111 }
112
113 byte[] bndbytes = boundary.getBytes(StandardCharsets.ISO_8859_1);
114 int bl = bndbytes.length;
115
116 String line;
117 parsing = true;
118 try {
119 /*
120 * Skip any kind of junk until we get to the first
121 * boundary line.
122 */
123 LineInputStream lin = new LineInputStream(in);
124 while ((line = lin.readLine()) != null) {
125 if (line.trim().equals(boundary))
126 break;
127 }
128 if (line == null)
129 throw new MessagingException("Missing start boundary");
130
131 /*
132 * Read and process body parts until we see the
133 * terminating boundary line (or EOF).
134 */
135 for (;;) {
136 /*
137 * Collect the headers for this body part.
138 */
139 InternetHeaders headers = new InternetHeaders(in);
140
141 if (!in.markSupported())
142 throw new MessagingException("Stream doesn't support mark");
143
144 ByteArrayOutputStream buf = new ByteArrayOutputStream();
145 int b;
146
147 /*
148 * Read and save the content bytes in buf.
149 */
150 while ((b = in.read()) >= 0) {
151 if (b == '\r' || b == '\n') {
152 /*
153 * Found the end of a line, check whether the
154 * next line is a boundary.
155 */
156 int i;
157 in.mark(bl + 4 + 1); // "4" for possible "--\r\n"
158 if (b == '\r' && in.read() != '\n') {
159 in.reset();
160 in.mark(bl + 4);
161 }
162 // read bytes, matching against the boundary
163 for (i = 0; i < bl; i++)
164 if (in.read() != bndbytes[i])
165 break;
166 if (i == bl) {
167 int b2 = in.read();
168 // check for end of line
169 if (b2 == '\n')
170 break; // got it! break out of the while loop
171 if (b2 == '\r') {
172 in.mark(1);
173 if (in.read() != '\n')
174 in.reset();
175 break; // got it! break out of the while loop
176 }
177 }
178 // failed to match, reset and proceed normally
179 in.reset();
180 }
181 buf.write(b);
182 }
183
184 /*
185 * Create a SunV3BodyPart to represent this body part.
186 */
187 SunV3BodyPart body =
188 new SunV3BodyPart(headers, buf.toByteArray());
189 addBodyPart(body);
190 if (b < 0)
191 break;
192 }
193 } catch (IOException e) {
194 throw new MessagingException("IO Error"); // XXX
195 } finally {
196 parsing = false;
197 }
198
199 parsed = true;
200 }
201 }