/*
   * Parse the contents of this multipart message and create the
   * child body parts.
   */
  protected synchronized void parse() throws MessagingException {
    if (parsed) return;

    InputStream in = null;

    try {
      in = ds.getInputStream();
      if (!(in instanceof ByteArrayInputStream) && !(in instanceof BufferedInputStream))
        in = new BufferedInputStream(in);
    } catch (Exception ex) {
      throw new MessagingException("No inputstream from datasource");
    }

    String line;
    int bl = boundary.length();
    byte[] bndbytes = new byte[bl];
    boundary.getBytes(0, bl, bndbytes, 0);

    try {
      /*
       * Skip any kind of junk until we get to the first
       * boundary line.
       */
      LineInputStream lin = new LineInputStream(in);
      while ((line = lin.readLine()) != null) {
        if (line.trim().equals(boundary)) break;
      }
      if (line == null) throw new MessagingException("Missing start boundary");

      /*
       * Read and process body parts until we see the
       * terminating boundary line (or EOF).
       */
      for (; ; ) {
        /*
         * Collect the headers for this body part.
         */
        InternetHeaders headers = new InternetHeaders(in);

        if (!in.markSupported()) throw new MessagingException("Stream doesn't support mark");

        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        int b;

        /*
         * Read and save the content bytes in buf.
         */
        while ((b = in.read()) >= 0) {
          if (b == '\r' || b == '\n') {
            /*
             * Found the end of a line, check whether the
             * next line is a boundary.
             */
            int i;
            in.mark(bl + 4 + 1); // "4" for possible "--\r\n"
            if (b == '\r' && in.read() != '\n') {
              in.reset();
              in.mark(bl + 4);
            }
            // read bytes, matching against the boundary
            for (i = 0; i < bl; i++) if (in.read() != bndbytes[i]) break;
            if (i == bl) {
              int b2 = in.read();
              // check for end of line
              if (b2 == '\n') break; // got it!  break out of the while loop
              if (b2 == '\r') {
                in.mark(1);
                if (in.read() != '\n') in.reset();
                break; // got it!  break out of the while loop
              }
            }
            // failed to match, reset and proceed normally
            in.reset();
          }
          buf.write(b);
        }

        /*
         * Create a SunV3BodyPart to represent this body part.
         */
        SunV3BodyPart body = new SunV3BodyPart(headers, buf.toByteArray());
        addBodyPart(body);
        if (b < 0) break;
      }
    } catch (IOException e) {
      throw new MessagingException("IO Error"); // XXX
    }

    parsed = true;
  }
  /*
   * This method checks for content-type
   * based on which, it processes and
   * fetches the content of the message
   */
  public static void writePart(Part p, MailInfo mailInfo) throws Exception {
    if (p instanceof Message)
      // Call methos writeEnvelope
      writeEnvelope((Message) p, mailInfo);

    log.info("----------------------------");
    log.info("CONTENT-TYPE: " + p.getContentType());

    // check if the content is plain text
    if (p.isMimeType("text/plain")) {
      log.info("This is plain text");
      log.info("---------------------------");
      log.info((String) p.getContent());

      mailInfo.setBody(p.getContent().toString());
    }
    // check if the content has attachment
    else if (p.isMimeType("multipart/*")) {
      log.info("This is a Multipart");
      log.info("---------------------------");
      Multipart mp = (Multipart) p.getContent();
      int count = mp.getCount();
      for (int i = 0; i < count; i++) writePart(mp.getBodyPart(i), mailInfo);
    }
    // check if the content is a nested message
    else if (p.isMimeType("message/rfc822")) {
      log.info("This is a Nested Message");
      log.info("---------------------------");
      writePart((Part) p.getContent(), mailInfo);
    }
    // check if the content is an inline image
    else if (p.isMimeType("image/jpeg")) {
      log.info("--------> image/jpeg");
      Object o = p.getContent();
      InputStream x = (InputStream) o;
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      IOUtils.copy(x, bos);
      NamedContent namedContent = new NamedContent();
      namedContent.setName(p.getFileName());
      namedContent.setType(p.getContentType());
      namedContent.setContent(bos.toByteArray());
      mailInfo.getAttachments().add(namedContent);
    } else if (p.isMimeType("image/png")) {
      log.info("--------> image/png");
      Object o = p.getContent();
      InputStream x = (InputStream) o;
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      IOUtils.copy(x, bos);
      NamedContent namedContent = new NamedContent();
      namedContent.setName(p.getFileName());
      namedContent.setType(p.getContentType());
      namedContent.setContent(bos.toByteArray());
      mailInfo.getAttachments().add(namedContent);
    } else if (p.getContentType().contains("image/")) {
      log.info("content type" + p.getContentType());
      File f = new File("image" + new Date().getTime() + ".jpg");
      DataOutputStream output =
          new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
      com.sun.mail.util.BASE64DecoderStream test =
          (com.sun.mail.util.BASE64DecoderStream) p.getContent();
      byte[] buffer = new byte[1024];
      int bytesRead;
      while ((bytesRead = test.read(buffer)) != -1) {
        output.write(buffer, 0, bytesRead);
      }
    } else {
      Object o = p.getContent();
      if (o instanceof String) {
        log.info("This is a string");
        log.info("---------------------------");
        log.info((String) o);
      } else if (o instanceof InputStream) {
        log.info("This is just an input stream");
        log.info("---------------------------");
        InputStream is = (InputStream) o;
        is = (InputStream) o;
        int c;
        while ((c = is.read()) != -1) System.out.write(c);
      } else {
        log.info("This is an unknown type");
        log.info("---------------------------");
        log.info(o.toString());
      }
    }
  }