45 * pull parser.
46 *
47 * @author Jitendra Kotamraju
48 */
49 public class MIMEMessage implements Closeable {
50
51 private static final Logger LOGGER = Logger.getLogger(MIMEMessage.class.getName());
52
53 MIMEConfig config;
54
55 private final InputStream in;
56 private final Iterator<MIMEEvent> it;
57 private boolean parsed; // true when entire message is parsed
58 private MIMEPart currentPart;
59 private int currentIndex;
60
61 private final List<MIMEPart> partsList = new ArrayList<MIMEPart>();
62 private final Map<String, MIMEPart> partsMap = new HashMap<String, MIMEPart>();
63
64 /**
65 * @see MIMEMessage(InputStream, String, MIMEConfig)
66 */
67 public MIMEMessage(InputStream in, String boundary) {
68 this(in, boundary, new MIMEConfig());
69 }
70
71 /**
72 * Creates a MIME message from the content's stream. The content stream
73 * is closed when EOF is reached.
74 *
75 * @param in MIME message stream
76 * @param boundary the separator for parts(pass it without --)
77 * @param config various configuration parameters
78 */
79 public MIMEMessage(InputStream in, String boundary, MIMEConfig config) {
80 this.in = in;
81 this.config = config;
82 MIMEParser parser = new MIMEParser(in, boundary, config);
83 it = parser.iterator();
84
85 if (config.isParseEagerly()) {
114 LOGGER.log(Level.FINE, "index={0}", index);
115 MIMEPart part = (index < partsList.size()) ? partsList.get(index) : null;
116 if (parsed && part == null) {
117 throw new MIMEParsingException("There is no " + index + " attachment part ");
118 }
119 if (part == null) {
120 // Parsing will done lazily and will be driven by reading the part
121 part = new MIMEPart(this);
122 partsList.add(index, part);
123 }
124 LOGGER.log(Level.FINE, "Got attachment at index={0} attachment={1}", new Object[] {index, part});
125 return part;
126 }
127
128 /**
129 * Creates a lazy attachment for a given Content-ID. It doesn't validate
130 * if the message contains an attachment with the given Content-ID. To
131 * do the validation, the message needs to be parsed. The parsing of the
132 * message is done lazily and is done while reading the bytes of the part.
133 *
134 * @param contentId Content-ID of the part, expects Content-ID without <, >
135 * @return attachemnt part
136 */
137 public MIMEPart getPart(String contentId) {
138 LOGGER.log(Level.FINE, "Content-ID={0}", contentId);
139 MIMEPart part = getDecodedCidPart(contentId);
140 if (parsed && part == null) {
141 throw new MIMEParsingException("There is no attachment part with Content-ID = " + contentId);
142 }
143 if (part == null) {
144 // Parsing is done lazily and is driven by reading the part
145 part = new MIMEPart(this, contentId);
146 partsMap.put(contentId, part);
147 }
148 LOGGER.log(Level.FINE, "Got attachment for Content-ID={0} attachment={1}", new Object[] {contentId, part});
149 return part;
150 }
151
152 // this is required for Indigo interop, it writes content-id without escaping
153 private MIMEPart getDecodedCidPart(String cid) {
154 MIMEPart part = partsMap.get(cid);
160 } catch (UnsupportedEncodingException ue) {
161 // Ignore it
162 }
163 }
164 }
165 return part;
166 }
167
168 /**
169 * Parses the whole MIME message eagerly
170 */
171 public final void parseAll() {
172 while (makeProgress()) {
173 // Nothing to do
174 }
175 }
176
177 /**
178 * Closes all parsed {@link com.sun.xml.internal.org.jvnet.mimepull.MIMEPart parts}.
179 * This method is safe to call even if parsing of message failed.
180 * <p/>
181 * Does not throw {@link com.sun.xml.internal.org.jvnet.mimepull.MIMEParsingException} if an
182 * error occurred during closing a MIME part. The exception (if any) is
183 * still logged.
184 */
185 @Override
186 public void close() {
187 close(partsList);
188 close(partsMap.values());
189 }
190
191 private void close(final Collection<MIMEPart> parts) {
192 for (final MIMEPart part : parts) {
193 try {
194 part.close();
195 } catch (final MIMEParsingException closeError) {
196 LOGGER.log(Level.FINE, "Exception during closing MIME part", closeError);
197 }
198 }
199 }
200
201 /**
|
45 * pull parser.
46 *
47 * @author Jitendra Kotamraju
48 */
49 public class MIMEMessage implements Closeable {
50
51 private static final Logger LOGGER = Logger.getLogger(MIMEMessage.class.getName());
52
53 MIMEConfig config;
54
55 private final InputStream in;
56 private final Iterator<MIMEEvent> it;
57 private boolean parsed; // true when entire message is parsed
58 private MIMEPart currentPart;
59 private int currentIndex;
60
61 private final List<MIMEPart> partsList = new ArrayList<MIMEPart>();
62 private final Map<String, MIMEPart> partsMap = new HashMap<String, MIMEPart>();
63
64 /**
65 * @see #MIMEMessage(InputStream, String, MIMEConfig)
66 *
67 * @param in MIME message stream
68 * @param boundary the separator for parts(pass it without --)
69 */
70 public MIMEMessage(InputStream in, String boundary) {
71 this(in, boundary, new MIMEConfig());
72 }
73
74 /**
75 * Creates a MIME message from the content's stream. The content stream
76 * is closed when EOF is reached.
77 *
78 * @param in MIME message stream
79 * @param boundary the separator for parts(pass it without --)
80 * @param config various configuration parameters
81 */
82 public MIMEMessage(InputStream in, String boundary, MIMEConfig config) {
83 this.in = in;
84 this.config = config;
85 MIMEParser parser = new MIMEParser(in, boundary, config);
86 it = parser.iterator();
87
88 if (config.isParseEagerly()) {
117 LOGGER.log(Level.FINE, "index={0}", index);
118 MIMEPart part = (index < partsList.size()) ? partsList.get(index) : null;
119 if (parsed && part == null) {
120 throw new MIMEParsingException("There is no " + index + " attachment part ");
121 }
122 if (part == null) {
123 // Parsing will done lazily and will be driven by reading the part
124 part = new MIMEPart(this);
125 partsList.add(index, part);
126 }
127 LOGGER.log(Level.FINE, "Got attachment at index={0} attachment={1}", new Object[] {index, part});
128 return part;
129 }
130
131 /**
132 * Creates a lazy attachment for a given Content-ID. It doesn't validate
133 * if the message contains an attachment with the given Content-ID. To
134 * do the validation, the message needs to be parsed. The parsing of the
135 * message is done lazily and is done while reading the bytes of the part.
136 *
137 * @param contentId Content-ID of the part, expects Content-ID without {@code <, >}
138 * @return attachemnt part
139 */
140 public MIMEPart getPart(String contentId) {
141 LOGGER.log(Level.FINE, "Content-ID={0}", contentId);
142 MIMEPart part = getDecodedCidPart(contentId);
143 if (parsed && part == null) {
144 throw new MIMEParsingException("There is no attachment part with Content-ID = " + contentId);
145 }
146 if (part == null) {
147 // Parsing is done lazily and is driven by reading the part
148 part = new MIMEPart(this, contentId);
149 partsMap.put(contentId, part);
150 }
151 LOGGER.log(Level.FINE, "Got attachment for Content-ID={0} attachment={1}", new Object[] {contentId, part});
152 return part;
153 }
154
155 // this is required for Indigo interop, it writes content-id without escaping
156 private MIMEPart getDecodedCidPart(String cid) {
157 MIMEPart part = partsMap.get(cid);
163 } catch (UnsupportedEncodingException ue) {
164 // Ignore it
165 }
166 }
167 }
168 return part;
169 }
170
171 /**
172 * Parses the whole MIME message eagerly
173 */
174 public final void parseAll() {
175 while (makeProgress()) {
176 // Nothing to do
177 }
178 }
179
180 /**
181 * Closes all parsed {@link com.sun.xml.internal.org.jvnet.mimepull.MIMEPart parts}.
182 * This method is safe to call even if parsing of message failed.
183 *
184 * <p> Does not throw {@link com.sun.xml.internal.org.jvnet.mimepull.MIMEParsingException} if an
185 * error occurred during closing a MIME part. The exception (if any) is
186 * still logged.
187 */
188 @Override
189 public void close() {
190 close(partsList);
191 close(partsMap.values());
192 }
193
194 private void close(final Collection<MIMEPart> parts) {
195 for (final MIMEPart part : parts) {
196 try {
197 part.close();
198 } catch (final MIMEParsingException closeError) {
199 LOGGER.log(Level.FINE, "Exception during closing MIME part", closeError);
200 }
201 }
202 }
203
204 /**
|