package org.jboss.resteasy.plugins.providers.multipart;

import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;

import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
import org.apache.james.mime4j.codec.Base64InputStream;
import org.apache.james.mime4j.dom.Body;
import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.Header;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.parser.ContentHandler;
import org.apache.james.mime4j.stream.BodyDescriptor;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.RawField;
import org.apache.james.mime4j.util.ByteArrayBuffer;
import org.apache.james.mime4j.util.ByteSequence;

// Imports added due to repackaging
import org.apache.james.mime4j.message.BodyFactory;
import org.apache.james.mime4j.message.BodyPart;
import org.apache.james.mime4j.message.HeaderImpl;
import org.apache.james.mime4j.message.MessageImpl;
import org.apache.james.mime4j.message.MultipartImpl;
import org.apache.james.mime4j.util.MimeUtil;


A ContentHandler for building an Entity to be used in conjunction with a MimeStreamParser. This class was copied nearly verbatim from org.apache.james.mime4j.message.EntityBuilder It was duplicated because multipart-providers always wants a BinaryBody and never a TextBody. Unfortunately, there's no easy to get this in apache-mime4j. Further, the logical place to extend and override, "EntityBuilder", is a package-private class.

Therefore we duplicate EntityBuilder here. All code is identical except:

  • package changed
  • class renamed
  • constructor renamed
  • additional imports added due to repackaging of the class
  • body(BodyDescriptor bd, final InputStream is) - Method which unilaterally returns a BinaryBody.

This file may not follow RESTEasy formatting standards. This is to make it easier to diff against the original EntityBuilder in the future when mime4j is updated again.

/** * A <code>ContentHandler</code> for building an <code>Entity</code> to be * used in conjunction with a {@link org.apache.james.mime4j.parser.MimeStreamParser}. * * This class was copied nearly verbatim from org.apache.james.mime4j.message.EntityBuilder * It was duplicated because multipart-providers always wants a BinaryBody and never a TextBody. * Unfortunately, there's no easy to get this in apache-mime4j. Further, the * logical place to extend and override, "EntityBuilder", is a package-private class. * <p> * Therefore we duplicate EntityBuilder here. * All code is identical except: * <ul> * <li>package changed</li> * <li>class renamed</li> * <li>constructor renamed</li> * <li>additional imports added due to repackaging of the class</li> * <li>body(BodyDescriptor bd, final InputStream is) - Method which unilaterally returns a BinaryBody.</li> * </ul> * <p> * This file may not follow RESTEasy formatting standards. This is to make it easier to diff against the original EntityBuilder in the future when mime4j is updated again. */
class Mime4jWorkaroundBinaryEntityBuilder implements ContentHandler { private final Entity entity; private final BodyFactory bodyFactory; private final Stack<Object> stack; Mime4jWorkaroundBinaryEntityBuilder( final Entity entity, final BodyFactory bodyFactory) { this.entity = entity; this.bodyFactory = bodyFactory; this.stack = new Stack<Object>(); } private void expect(Class<?> c) { if (!c.isInstance(stack.peek())) { throw new IllegalStateException("Internal stack error: " + "Expected '" + c.getName() + "' found '" + stack.peek().getClass().getName() + "'"); } }
See Also:
  • startMessage.startMessage()
/** * @see org.apache.james.mime4j.parser.ContentHandler#startMessage() */
public void startMessage() throws MimeException { if (stack.isEmpty()) { stack.push(this.entity); } else { expect(Entity.class); Message m = new MessageImpl(); ((Entity) stack.peek()).setBody(m); stack.push(m); } }
See Also:
  • endMessage.endMessage()
/** * @see org.apache.james.mime4j.parser.ContentHandler#endMessage() */
public void endMessage() throws MimeException { expect(Message.class); stack.pop(); }
See Also:
  • startHeader.startHeader()
/** * @see org.apache.james.mime4j.parser.ContentHandler#startHeader() */
public void startHeader() throws MimeException { stack.push(new HeaderImpl()); }
See Also:
  • field.field(RawField)
/** * @see org.apache.james.mime4j.parser.ContentHandler#field(RawField) */
public void field(Field field) throws MimeException { expect(Header.class); ((Header) stack.peek()).addField(field); }
See Also:
  • endHeader.endHeader()
/** * @see org.apache.james.mime4j.parser.ContentHandler#endHeader() */
public void endHeader() throws MimeException { expect(Header.class); Header h = (Header) stack.pop(); expect(Entity.class); ((Entity) stack.peek()).setHeader(h); }
See Also:
  • startMultipart.startMultipart(BodyDescriptor)
/** * @see org.apache.james.mime4j.parser.ContentHandler#startMultipart(org.apache.james.mime4j.stream.BodyDescriptor) */
public void startMultipart(final BodyDescriptor bd) throws MimeException { expect(Entity.class); final Entity e = (Entity) stack.peek(); final String subType = bd.getSubType(); final Multipart multiPart = new MultipartImpl(subType); e.setBody(multiPart); stack.push(multiPart); }
See Also:
  • body.body(BodyDescriptor, InputStream)
/** * @see org.apache.james.mime4j.parser.ContentHandler#body(org.apache.james.mime4j.stream.BodyDescriptor, java.io.InputStream) */
public void body(BodyDescriptor bd, final InputStream is) throws MimeException, IOException { expect(Entity.class); final String enc = bd.getTransferEncoding(); final Body body; final InputStream decodedStream; if (MimeUtil.ENC_BASE64.equals(enc)) { decodedStream = new Base64InputStream(is); } else if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(enc)) { decodedStream = new QuotedPrintableInputStream(is); } else { decodedStream = is; } //Code change here to unilaterally use binaryBody //Code left commented out here to make diffs easy in the future when apache-mime4j updates. //if (bd.getMimeType().startsWith("text/")) { // body = bodyFactory.textBody(is, bd.getCharset()); //} else { body = bodyFactory.binaryBody(decodedStream); //} Entity entity = ((Entity) stack.peek()); entity.setBody(body); }
See Also:
  • endMultipart.endMultipart()
/** * @see org.apache.james.mime4j.parser.ContentHandler#endMultipart() */
public void endMultipart() throws MimeException { stack.pop(); }
See Also:
  • startBodyPart.startBodyPart()
/** * @see org.apache.james.mime4j.parser.ContentHandler#startBodyPart() */
public void startBodyPart() throws MimeException { expect(Multipart.class); BodyPart bodyPart = new BodyPart(); ((Multipart) stack.peek()).addBodyPart(bodyPart); stack.push(bodyPart); }
See Also:
  • endBodyPart.endBodyPart()
/** * @see org.apache.james.mime4j.parser.ContentHandler#endBodyPart() */
public void endBodyPart() throws MimeException { expect(BodyPart.class); stack.pop(); }
See Also:
  • epilogue.epilogue(InputStream)
/** * @see org.apache.james.mime4j.parser.ContentHandler#epilogue(java.io.InputStream) */
public void epilogue(InputStream is) throws MimeException, IOException { expect(MultipartImpl.class); ByteSequence bytes = loadStream(is); ((MultipartImpl) stack.peek()).setEpilogueRaw(bytes); }
See Also:
  • preamble.preamble(InputStream)
/** * @see org.apache.james.mime4j.parser.ContentHandler#preamble(java.io.InputStream) */
public void preamble(InputStream is) throws MimeException, IOException { expect(MultipartImpl.class); ByteSequence bytes = loadStream(is); ((MultipartImpl) stack.peek()).setPreambleRaw(bytes); }
Unsupported.
See Also:
  • raw.raw(InputStream)
/** * Unsupported. * @see org.apache.james.mime4j.parser.ContentHandler#raw(java.io.InputStream) */
public void raw(InputStream is) throws MimeException, IOException { throw new UnsupportedOperationException("Not supported"); } private static ByteSequence loadStream(InputStream in) throws IOException { ByteArrayBuffer bab = new ByteArrayBuffer(64); int b; while ((b = in.read()) != -1) { bab.append(b); } return bab; } }