rineholt    2002/06/30 12:59:04

  Modified:    java/src/org/apache/axis Message.java MessageContext.java
               java/src/org/apache/axis/attachments Attachments.java
                        AttachmentsImpl.java
                        MultiPartRelatedInputStream.java
               java/src/org/apache/axis/client Call.java
               java/src/org/apache/axis/transport/http AxisServlet.java
               java/src/org/apache/axis/utils JavaUtils.java
                        axisNLS.properties
  Added:       java/src/org/apache/axis/attachments DimeBodyPart.java
                        DimeDelimitedInputStream.java DimeMultiPart.java
                        DimeTypeNameFormat.java
                        MultiPartDimeInputStream.java
                        MultiPartInputStream.java
  Log:
  Support for DIME according to the new released spec at:
  http://msdn.microsoft.com/library/en-us/dnglobspec/html/draft-nielsen-dime-02.txt
  
  Revision  Changes    Path
  1.76      +2 -3      xml-axis/java/src/org/apache/axis/Message.java
  
  Index: Message.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/Message.java,v
  retrieving revision 1.75
  retrieving revision 1.76
  diff -u -r1.75 -r1.76
  --- Message.java      29 Jun 2002 16:39:51 -0000      1.75
  +++ Message.java      30 Jun 2002 19:59:04 -0000      1.76
  @@ -96,7 +96,6 @@
       // MIME parts defined for messages.
       public static final String MIME_MULTIPART_RELATED = "multipart/related";
   
  -    // NOT SUPPORTED NOW
       public static final String MIME_APPLICATION_DIME = "application/dime";
   
       /** Default Attachments Implementation class */
  @@ -385,10 +384,10 @@
       }
   
       //This will have to give way someday to HTTP Chunking but for now kludge.
  -    public int getContentLength() throws org.apache.axis.AxisFault {
  +    public long getContentLength() throws org.apache.axis.AxisFault {
           //Force serialization if it hasn't happend it.
           //Rick Rineholt fix this later.
  -        int ret = mSOAPPart.getAsBytes().length;
  +        long ret = mSOAPPart.getAsBytes().length;
           if (mAttachments != null && 0 < mAttachments.getAttachmentCount()) {
               ret = mAttachments.getContentLength();
           }
  
  
  
  1.106     +17 -2     xml-axis/java/src/org/apache/axis/MessageContext.java
  
  Index: MessageContext.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/MessageContext.java,v
  retrieving revision 1.105
  retrieving revision 1.106
  diff -u -r1.105 -r1.106
  --- MessageContext.java       30 Jun 2002 18:15:46 -0000      1.105
  +++ MessageContext.java       30 Jun 2002 19:59:04 -0000      1.106
  @@ -55,6 +55,7 @@
   
   package org.apache.axis ;
   
  +import org.apache.axis.attachments.Attachments;
   import org.apache.axis.client.AxisClient;
   import org.apache.axis.description.OperationDesc;
   import org.apache.axis.description.ServiceDesc;
  @@ -437,8 +438,22 @@
        */
       public void setResponseMessage(Message respMsg) {
           responseMessage = respMsg ;
  -        if (responseMessage != null) responseMessage.setMessageContext(this);
  -    };
  +        if (responseMessage != null){
  +          responseMessage.setMessageContext(this);
  +
  +          //if we have received attachments of a particular type
  +          // than that should be the default type to send.
  +          Message reqMsg= getRequestMessage(); 
  +          if( null != reqMsg){
  +            Attachments reqAttch= reqMsg.getAttachmentsImpl();
  +            Attachments respAttch= respMsg.getAttachmentsImpl();
  +            if(null != reqAttch  && null != respAttch){
  +              if(respAttch.getSendType() == Attachments.SEND_TYPE_NOTSET)  
  +                respAttch.setSendType(reqAttch.getSendType());//only if not 
explicity set.
  +            }
  +          }
  +        }
  +    }
   
       /**
        * Return the current (i.e. request before the pivot, response after)
  
  
  
  1.9       +35 -1     xml-axis/java/src/org/apache/axis/attachments/Attachments.java
  
  Index: Attachments.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/attachments/Attachments.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Attachments.java  24 Jun 2002 12:34:51 -0000      1.8
  +++ Attachments.java  30 Jun 2002 19:59:04 -0000      1.9
  @@ -194,7 +194,7 @@
        *
        * @throws org.apache.axis.AxisFault
        */
  -    public int getContentLength() throws org.apache.axis.AxisFault;
  +    public long getContentLength() throws org.apache.axis.AxisFault;
   
       /**
        * Write the content to the stream.
  @@ -231,4 +231,38 @@
        * @return True if value should be treated as an attchment.
        */
       public boolean isAttachment(Object value);
  +
  +
  +    /** Use the default attatchment send type. */
  +    public final int SEND_TYPE_NOTSET = 1; 
  +
  +    /** Use the SOAP with MIME attatchment send type. */
  +    public final int SEND_TYPE_MIME = 2; //use mime
  +
  +    /** Use the DIME attatchment type. */
  +    public final int  SEND_TYPE_DIME= 3; //use dime;
  +
  +    final int SEND_TYPE_MAX = 3;
  +
  +    /** The default attatchment type. MIME */
  +    final int SEND_TYPE_DEFAULT = SEND_TYPE_MIME; 
  +
  +    /**
  +     * Set the format for attachments. 
  +     *
  +     * @param the format to send.
  +     *      SEND_TYPE_MIME for Multipart Releated Mail type attachments. 
  +     *      SEND_TYPE_DIME for DIME type attachments. 
  +     */
  +
  +    public void setSendType( int sendtype);
  +
  +    /**
  +     * Determine if an object is to be treated as an attchment. 
  +     *
  +     *
  +     * @return SEND_TYPE_MIME, SEND_TYPE_DIME,  SEND_TYPE_NOTSET  
  +     */
  +
  +    public int getSendType();
   }
  
  
  
  1.19      +102 -21   
xml-axis/java/src/org/apache/axis/attachments/AttachmentsImpl.java
  
  Index: AttachmentsImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/attachments/AttachmentsImpl.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- AttachmentsImpl.java      24 Jun 2002 13:19:10 -0000      1.18
  +++ AttachmentsImpl.java      30 Jun 2002 19:59:04 -0000      1.19
  @@ -90,8 +90,12 @@
       /**
        * The actual stream to manage the multi-related input stream.
        */
  -    protected org.apache.axis.attachments.MultiPartRelatedInputStream mpartStream =
  +    protected MultiPartInputStream  mpartStream =
               null;
  +    /**
  +     * The form of the attachments, whether MIME or DIME.
  +     */
  +    protected int sendtype= Attachments.SEND_TYPE_NOTSET;
   
       /**
        * This is the content location as specified in SOAP with Attachments.
  @@ -132,7 +136,7 @@
   
                   // Process the input stream for headers to determine the mime
                   // type.
  -                // TODO
  +                //TODO -- This is for transports that do not process headers.
               } else {
                   java.util.StringTokenizer st =
                           new java.util.StringTokenizer(contentType, " \t;");
  @@ -142,6 +146,7 @@
   
                       if (mimetype.equalsIgnoreCase(
                               org.apache.axis.Message.MIME_MULTIPART_RELATED)) {
  +                        sendtype=  SEND_TYPE_MIME;     
                           mpartStream =
                                   new 
org.apache.axis.attachments.MultiPartRelatedInputStream(
                                           contentType,
  @@ -165,10 +170,13 @@
                           soapPart = new org.apache.axis.SOAPPart(null,
                                   mpartStream,
                                   false);
  -                    } else if (mimetype.equalsIgnoreCase(
  -                            org.apache.axis.Message.MIME_APPLICATION_DIME)) {    // 
do nothing today.
  -
  -                        // is= new DIMEInputStreamManager(is);
  +                     } else if 
(mimetype.equalsIgnoreCase(org.apache.axis.Message.MIME_APPLICATION_DIME)) { 
  +                         try{
  +                            mpartStream=
  +                             new MultiPartDimeInputStream( (java.io.InputStream) 
intialContents);
  +                             soapPart = new org.apache.axis.SOAPPart(null, 
mpartStream, false);
  +                         }catch(Exception e){ throw 
org.apache.axis.AxisFault.makeFault(e);}
  +                         sendtype=  SEND_TYPE_DIME;     
                       }
                   }
               }
  @@ -206,6 +214,10 @@
       public Part removeAttachmentPart(String reference)
               throws org.apache.axis.AxisFault {
   
  +        multipart = null;
  +        
  +        dimemultipart = null;
  +
           mergeinAttachments();
   
           Part removedPart = getAttachmentByReference(reference);
  @@ -232,6 +244,10 @@
       public Part addAttachmentPart(Part newPart)
               throws org.apache.axis.AxisFault {
   
  +        multipart = null;
  +
  +        dimemultipart = null;
  +
           mergeinAttachments();
   
           Part oldPart = (Part) attachments.put(newPart.getContentId(), newPart);
  @@ -262,6 +278,10 @@
       public Part createAttachmentPart(Object datahandler)
               throws org.apache.axis.AxisFault {
   
  +        multipart = null;
  +
  +        dimemultipart = null;
  +
           mergeinAttachments();
   
           if (!(datahandler instanceof javax.activation.DataHandler)) {
  @@ -289,6 +309,8 @@
       public void setAttachmentParts(java.util.Collection parts)
               throws org.apache.axis.AxisFault {
   
  +        multipart = null;
  +        dimemultipart = null;
           mergeinAttachments();
           attachments.clear();
           orderedAttachments.clear();
  @@ -395,13 +417,16 @@
   
           try {
               this.soapPart = (SOAPPart) newRoot;
  +            multipart = null;
  +            dimemultipart = null;
           } catch (ClassCastException e) {
               throw new ClassCastException(JavaUtils.getMessage("onlySOAPParts"));
           }
       }
   
       /** Field multipart           */
  -    public javax.mail.internet.MimeMultipart multipart = null;
  +    javax.mail.internet.MimeMultipart multipart = null;
  +    DimeMultiPart dimemultipart = null;
   
       /**
        * Get the content length of the stream.
  @@ -410,22 +435,55 @@
        *
        * @throws org.apache.axis.AxisFault
        */
  -    public int getContentLength() throws org.apache.axis.AxisFault {
  +    public long getContentLength() throws org.apache.axis.AxisFault {
   
           mergeinAttachments();
   
  +        int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT :   
this.sendtype;       
  +
           try {
  -            return (int) org.apache.axis.attachments.MimeUtils.getContentLength(
  -                    (multipart != null)
  -                    ? multipart
  -                    : (multipart = org.apache.axis.attachments.MimeUtils.createMP(
  -                            soapPart.getAsString(), orderedAttachments)));
  +              if(sendtype == SEND_TYPE_MIME)
  +                 return (int)org.apache.axis.attachments.MimeUtils.getContentLength(
  +                                multipart != null ? multipart : (multipart = 
org.apache.axis.attachments.MimeUtils.createMP(soapPart.getAsString(), 
orderedAttachments)));
  +              else if (sendtype == SEND_TYPE_DIME)return 
createDimeMessage().getTransmissionSize();
           } catch (Exception e) {
               throw AxisFault.makeFault(e);
           }
  +        return 0;
       }
   
       /**
  +     * Creates the DIME message 
  +     *
  +     * @return
  +     *
  +     * @throws org.apache.axis.AxisFault
  +     */
  +    protected DimeMultiPart createDimeMessage() throws org.apache.axis.AxisFault{
  +        int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT :   
this.sendtype;       
  +        if (sendtype == SEND_TYPE_DIME){
  +           if(dimemultipart== null){
  +
  +              dimemultipart= new DimeMultiPart(); 
  +              dimemultipart.addBodyPart(new DimeBodyPart(
  +                soapPart.getAsBytes(), DimeTypeNameFormat.URI,
  +                "http://schemas.xmlsoap.org/soap/envelope/";,
  +                  "uuid:714C6C40-4531-442E-A498-3AC614200295"));
  +
  +              for( java.util.Iterator i= orderedAttachments.iterator();
  +                i.hasNext(); ){
  +                AttachmentPart part= (AttachmentPart)i.next();
  +                    DataHandler dh= AttachmentUtils.
  +                      getActivationDataHandler(part);
  +                    dimemultipart.addBodyPart(new 
  +                      DimeBodyPart(dh,part.getContentId()));
  +              }
  +            }
  +        }
  +        return dimemultipart;
  +      }
  +
  +    /**
        * Write the content to the stream.
        *
        * @param os
  @@ -434,12 +492,17 @@
        */
       public void writeContentToStream(java.io.OutputStream os)
               throws org.apache.axis.AxisFault {
  +        int sendtype= this.sendtype == SEND_TYPE_NOTSET ?
  +                          SEND_TYPE_DEFAULT : this.sendtype;       
  +        try{    
   
           mergeinAttachments();
  +        if(sendtype == SEND_TYPE_MIME){        
           org.apache.axis.attachments.MimeUtils.writeToMultiPartStream(os,
                   (multipart != null)
                   ? multipart
  -                : (multipart = org.apache.axis.attachments.MimeUtils.createMP(
  +                : (multipart =
  +                   org.apache.axis.attachments.MimeUtils.createMP(
                           soapPart.getAsString(), orderedAttachments)));
   
           for (java.util.Iterator i = orderedAttachments.iterator();
  @@ -453,6 +516,8 @@
                   ((ManagedMemoryDataSource) ds).delete();
               }
           }
  +        }else if (sendtype == SEND_TYPE_DIME)createDimeMessage().write(os);
  +       }catch(Exception e){ throw org.apache.axis.AxisFault.makeFault(e);}
       }
   
       /**
  @@ -466,13 +531,17 @@
   
           mergeinAttachments();
   
  -        return org.apache.axis.attachments.MimeUtils.getContentType((multipart
  -                != null)
  -                ? multipart
  -                : (multipart =
  -                org.apache.axis.attachments.MimeUtils.createMP(
  -                        soapPart.getAsString(),
  -                        orderedAttachments)));
  +        int sendtype= this.sendtype == SEND_TYPE_NOTSET ? SEND_TYPE_DEFAULT :
  +               this.sendtype;       
  +        if(sendtype == SEND_TYPE_MIME)        
  +          return org.apache.axis.attachments.MimeUtils.getContentType((multipart
  +                  != null)
  +                  ? multipart
  +                  : (multipart =
  +                  org.apache.axis.attachments.MimeUtils.createMP(
  +                          soapPart.getAsString(),
  +                          orderedAttachments)));
  +        else return org.apache.axis.Message.MIME_APPLICATION_DIME;        
       }
   
       /**
  @@ -564,5 +633,17 @@
        */
       public Part createAttachmentPart() throws org.apache.axis.AxisFault {
           return new AttachmentPart();
  +    }
  +
  +    public void setSendType( int sendtype){
  +      if( sendtype < 1)
  +        throw new IllegalArgumentException("");
  +      if( sendtype > SEND_TYPE_MAX )
  +        throw new IllegalArgumentException("");
  +      this.sendtype= sendtype;  
  +    }
  +
  +    public int getSendType(){
  +      return sendtype;
       }
   }
  
  
  
  1.15      +1 -1      
xml-axis/java/src/org/apache/axis/attachments/MultiPartRelatedInputStream.java
  
  Index: MultiPartRelatedInputStream.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/attachments/MultiPartRelatedInputStream.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- MultiPartRelatedInputStream.java  29 Jun 2002 21:55:39 -0000      1.14
  +++ MultiPartRelatedInputStream.java  30 Jun 2002 19:59:04 -0000      1.15
  @@ -68,7 +68,7 @@
    *
    * @author Rick Rineholt
    */
  -public class MultiPartRelatedInputStream extends java.io.FilterInputStream {
  +public class MultiPartRelatedInputStream extends MultiPartInputStream{
   
       /** Field log           */
       protected static Log log =
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/attachments/DimeBodyPart.java
  
  Index: DimeBodyPart.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * @author Rick Rineholt 
   */
  
  package org.apache.axis.attachments;
  
  
  import java.io.IOException;
  import java.util.StringTokenizer;
  
  import javax.activation.*;
  
  import org.apache.axis.transport.http.HTTPConstants;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.axis.utils.JavaUtils;
  
  
  /**
   * This class is a single part for DIME mulitpart message. 
  
   DIME 1.0 format
   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | VERSION |B|E|C| TYPE_T| OPT_T |         OPTIONS_LENGTH        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          ID_LENGTH          |             TYPE_LENGTH         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          DATA_LENGTH                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                       OPTIONS + PADDING                       /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        ID + PADDING                           /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        TYPE + PADDING                         /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        DATA + PADDING                         /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  
  /**
   * Holds one attachment DIME part.
   */
  public class DimeBodyPart {
      protected static Log log =
          LogFactory.getLog(DimeBodyPart.class.getName());
  
      protected Object data = null;  
      protected DimeTypeNameFormat dtnf = null; 
      protected byte[] type = null; 
      protected byte[] id = null; 
      final static byte POSITION_FIRST = (byte) 0x04;
      final static byte POSITION_LAST = (byte) 0x02;
      private final static byte CHUNK = 0x01; //Means set the chunk bit 
      private final static byte CHUNK_NEXT = 0x2; //Means this was part of a CHUNK 
      private static int MAX_TYPE_LENGTH = (1 << 16) - 1;
      private static int MAX_ID_LENGTH = (1 << 16) - 1;
  
      static final long MAX_DWORD = 0xffffffffL;
  
      protected DimeBodyPart() {}; //do not use.
  
      /**
       * Create a DIME Attachment Part.
       * @param data a byte array containing the data as the attachment.
       * @param format the type format for the data.
       * @param type the type of the data
       * @param id  the ID for the DIME part.
       *
       */
      public DimeBodyPart(byte[] data, DimeTypeNameFormat format, 
        String type, String id) {
          System.arraycopy(data, 0, this.data = new byte[ data.length], 0, 
data.length);
          this.dtnf = format; 
          this.type = type.getBytes();
          if (this.type.length > MAX_TYPE_LENGTH)
              throw new IllegalArgumentException(JavaUtils.getMessage 
                      ("attach.dimetypeexceedsmax",
                      "" + this.type.length, "" + MAX_TYPE_LENGTH));
          this.id = id.getBytes();
          if (this.id.length > MAX_ID_LENGTH)
              throw new IllegalArgumentException(
                      JavaUtils.getMessage("attach.dimelengthexceedsmax", "" + 
this.id.length,
                          "" + MAX_ID_LENGTH));
      }
  
      /**
       * Create a DIME Attachment Part.
       * @param dh the data for the attachment as a JAF datahadler. 
       * @param format the type format for the data.
       * @param type the type of the data
       * @param id  the ID for the DIME part.
       *
       */
      public DimeBodyPart(DataHandler dh,
      DimeTypeNameFormat format, String type, String id) {
          this.data = dh;
          this.dtnf = format; 
          if (type == null || type.length() == 0)
              type = "application/octet-stream";
          this.type = type.getBytes();
          if (this.type.length > MAX_TYPE_LENGTH)
              throw new IllegalArgumentException(JavaUtils.getMessage(
                          "attach.dimetypeexceedsmax", 
                          "" + this.type.length, "" + MAX_TYPE_LENGTH));
          this.id = id.getBytes(); 
          if (this.id.length > MAX_ID_LENGTH)
              throw new IllegalArgumentException(JavaUtils.getMessage(
              "attach.dimelengthexceedsmax", 
              "" + this.id.length, "" + MAX_ID_LENGTH));
      }
  
      /**
       * Create a DIME Attachment Part.
       * @param dh the data for the attachment as a JAF datahadler. 
       *    The type and foramt is derived from the DataHandler.
       * @param id  the ID for the DIME part.
       *
       */
      public DimeBodyPart(DataHandler dh, String id) {
          this(dh, DimeTypeNameFormat.MIME, dh.getContentType(), id);
  
          String ct = dh.getContentType();
  
          if (ct != null) {
              ct = ct.trim();
              if (ct.toLowerCase().startsWith("application/uri")) {
                  StringTokenizer st = new StringTokenizer(ct, " \t;");
                  String t = st.nextToken(" \t;");
  
                  if (t.equalsIgnoreCase("application/uri")) {
                      for (; st.hasMoreTokens();) {
                          t = st.nextToken(" \t;");
                          if (t.equalsIgnoreCase("uri")) {
                              t = st.nextToken("=");
                              if (t != null) {
                                  t = t.trim();
                                  if (t.startsWith("\"")) t =
                                    t.substring(1);
  
                                  if (t.endsWith("\"")) t =
                                    t.substring(0, t.length() - 1);
                                  this.type = t.getBytes();
                                  this.dtnf = DimeTypeNameFormat.URI;
                              }
                              return;
                          } else if (t.equalsIgnoreCase("uri=")) {
                              t = st.nextToken(" \t;");
                              if (null != t && t.length() != 0) {
                                  t = t.trim();
                                  if (t.startsWith("\"")) t=
                                    t.substring(1);
                                  if (t.endsWith("\"")) t=
                                    t.substring(0, t.length() - 1);
                                  this.type = t.getBytes();
                                  this.dtnf = DimeTypeNameFormat.URI;
                                  return;
                              }
                          } else if (t.toLowerCase().startsWith("uri=")) {
                              if (-1 != t.indexOf('=')) {
                                  t = t.substring(t.indexOf('=')).trim();
                                  if (t.length() != 0) {
                                      t = t.trim();
                                      if (t.startsWith("\"")) t =
                                        t.substring(1);
  
                                      if (t.endsWith("\""))
                                       t = t.substring(0, t.length() - 1);
                                      this.type = t.getBytes();
                                      this.dtnf = DimeTypeNameFormat.URI;
                                      return;
                        
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }
  
      /**
       * Write to stream the data using maxchunk for the largest junk. 
       *
       */
      void write(java.io.OutputStream os, byte position, long maxchunk)
        throws java.io.IOException {
          if (maxchunk < 1) throw new IllegalArgumentException(
                      JavaUtils.getMessage("attach.dimeMaxChunkSize0", "" + 
maxchunk)); 
          if (maxchunk > MAX_DWORD) throw new IllegalArgumentException(
                      JavaUtils.getMessage("attach.dimeMaxChunkSize1", "" + 
maxchunk)); 
          if (data instanceof byte[]) send(os, position, (byte[]) data,
            maxchunk);
          if (data instanceof DataHandler) send(os, position,
          (DataHandler) data, maxchunk);
      }
  
      /**
       * Write to stream the data.
       *
       */
      void write(java.io.OutputStream os, byte position)
        throws java.io.IOException {
          write(os, position, MAX_DWORD);
      }
  
      private static final byte[] pad = new byte[4];
  
      void send(java.io.OutputStream os, byte position, byte[] data,
          final long maxchunk)throws java.io.IOException {
          send(os, position, data, 0, data.length, maxchunk);
      }
  
      void send(java.io.OutputStream os, byte position, byte[] data, 
          int offset, final int length, final long maxchunk)
          throws java.io.IOException {
  
          byte chunknext = 0;
  
          do {
              int sendlength = (int) Math.min(maxchunk, length - offset);
  
              sendChunk(os, position, data, offset, sendlength, (byte)
                  ((sendlength < (length - offset) ? CHUNK : 0)
                   | chunknext));
              offset += sendlength;
              chunknext = CHUNK_NEXT;
          }
          while (offset < length);
      }
  
      void send(java.io.OutputStream os, byte position, DataHandler dh,
          final long maxchunk) throws java.io.IOException {
          byte chunknext = 0;
  
          long dataSize = getDataSize();
          java.io.InputStream in = dh.getInputStream();
          byte[] readbuf = new byte[64 * 1024];
          int bytesread;
  
          sendHeader(os, position, dataSize, (byte) 0);
          long totalsent = 0;
  
          do {
              bytesread = in.read(readbuf);
              if (bytesread > 0) {
                  os.write(readbuf, 0, bytesread);
                  totalsent += bytesread;
              }
          }
          while (bytesread > -1);
          os.write(pad, 0, dimePadding(totalsent));
      }
  
      protected void sendChunk(java.io.OutputStream os,
      final byte position, 
          byte[] data, byte chunk) throws java.io.IOException {
        
          sendChunk(os, position, data, 0, data.length, chunk);
      }
  
      protected void sendChunk(java.io.OutputStream os,
          final byte position, byte[] data, int offset, int length,
          byte chunk) throws java.io.IOException {
  
          sendHeader(os, position, length, chunk);
          os.write(data, offset, length);
          os.write(pad, 0, dimePadding(length));
      }
  
      final  static byte CURRENT_OPT_T = (byte) 0; 
  
      protected void sendHeader(java.io.OutputStream os, 
      final byte position,
          long length, byte chunk) throws java.io.IOException {
          byte[] fixedHeader = new byte[12];
  
          //VERSION
          fixedHeader[0] = (DimeMultiPart.CURRENT_VERSION << 3) & 0xf8;
  
          // B, E, and C
          fixedHeader[0] |= (byte) ((position & (byte) 0x6)
           & ((chunk & CHUNK) != 0 ? ~POSITION_LAST : ~0) &  
                      ((chunk & CHUNK_NEXT) != 0 ? ~POSITION_FIRST : ~0));
          fixedHeader[0] |= (chunk & CHUNK);
  
          //TYPE_T 
          if ((chunk & CHUNK_NEXT) == 0) //If this is a follow on chunk dont send id 
again.
              fixedHeader[1] = (byte) ((dtnf.toByte() << 4) & 0xf0);
  
          //OPT_T 
          fixedHeader[1] |= (byte) (CURRENT_OPT_T & 0xf);
        
          //OPTION_LENGTH
          fixedHeader[2] = (byte) 0;
          fixedHeader[3] = (byte) 0;
  
          //ID_LENGTH
          if ((chunk & CHUNK_NEXT) == 0) { //If this is a follow on chunk dont send id 
again.
              fixedHeader[4] = (byte) ((id.length >>> 8) & 0xff);  
              fixedHeader[5] = (byte) ((id.length) & 0xff);  
          }
  
          //TYPE_LENGTH
          if ((chunk & CHUNK_NEXT) == 0) {
              fixedHeader[6] = (byte) ((type.length >>> 8) & 0xff);  
              fixedHeader[7] = (byte) ((type.length) & 0xff);  
          }
  
          //DATA_LENGTH
          fixedHeader[8] = (byte) ((length >>> 24) & 0xff);
          fixedHeader[9] = (byte) ((length >>> 16) & 0xff);  
          fixedHeader[10] = (byte) ((length >>> 8) & 0xff);  
          fixedHeader[11] = (byte) (length & 0xff);  
  
          os.write(fixedHeader);
  
          //OPTIONS + PADDING
          // (NONE)
  
          //ID + PADDING
          if ((chunk & CHUNK_NEXT) == 0) {
              os.write(id);
              os.write(pad, 0, dimePadding(id.length));
          }
  
          //TYPE + PADDING
          if ((chunk & CHUNK_NEXT) == 0) {
              os.write(type);
              os.write(pad, 0, dimePadding(type.length));
          }
      }
  
      final static int dimePadding(long l) {
          return (int) ((4L - (l & 0x3L)) & 0x03L);
      }
  
      long getTransmissionSize(long chunkSize) {
          long size = 0;
  
          size += id.length;
          size += dimePadding(id.length);
          size += type.length;
          size += dimePadding(type.length);
          //no options.
          long dataSize = getDataSize();
  
          long fullChunks = dataSize / chunkSize;
          long lastChunkSize = dataSize % chunkSize;
  
          if (0 != lastChunkSize) size += 12; //12 bytes for fixed header
          size += 12 * fullChunks; //add additional header size for each chunk.
          size += fullChunks * dimePadding(chunkSize);
          size += dimePadding(lastChunkSize);
          size += dataSize;
  
          return size;
      }
  
      long getTransmissionSize() {
          return getTransmissionSize(MAX_DWORD);
      }
  
      protected long getDataSize() {
          if (data instanceof byte[]) return ((byte[]) (data)).length;
          if (data instanceof DataHandler) 
            return getDataSize((DataHandler) data);
          return -1;
      }
  
      protected long getDataSize(DataHandler dh) {
          long dataSize = -1L;
  
          try {
              DataSource ds = dh.getDataSource();
  
              //Do files our selfs since this is costly to read in. Ask the file 
system.
              // This is 90% of the use of attachments.
              if (ds instanceof javax.activation.FileDataSource) {
                  javax.activation.FileDataSource fdh = 
                      (javax.activation.FileDataSource) ds;
                  java.io.File df = fdh.getFile();
  
                  if (!df.exists()) {
                      throw new RuntimeException(
                              JavaUtils.getMessage("noFile", 
                                  df.getAbsolutePath()));
                  }
                  dataSize = df.length();
              } else {
                  dataSize = 0;
                  java.io.InputStream in = ds.getInputStream();
                  byte[] readbuf = new byte[64 * 1024];
                  int bytesread;
  
                  do {
                      bytesread = in.read(readbuf);
                      if (bytesread > 0) dataSize += bytesread;
                  }
                  while (bytesread > -1);
                  in.close();
              }
          } catch (Exception e) {
              log.error(JavaUtils.getMessage("exception00"), e);
          }
          return dataSize;
      }
  }
  
  
  
  1.1                  
xml-axis/java/src/org/apache/axis/attachments/DimeDelimitedInputStream.java
  
  Index: DimeDelimitedInputStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.attachments;
  
  
  import java.io.IOException;
  
  import org.apache.axis.utils.JavaUtils;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.axis.AxisFault;
  import org.apache.axis.utils.JavaUtils;
  
  
  /**
   * @author Rick Rineholt 
   */
  
  /**
   * This class takes the input stream and turns it multiple streams. 
   DIME version 0 format
   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  ---
   | VERSION |B|E|C| TYPE_T| OPT_T |         OPTIONS_LENGTH        |   A
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          ID_LENGTH          |             TYPE_LENGTH         |   Always present 
12 bytes 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   even on chunked 
data.
   |                          DATA_LENGTH                          |   V
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  ---
   |                                                               /
   /                       OPTIONS + PADDING                       /
   /                     (absent for version 0)                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        ID + PADDING                           /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        TYPE + PADDING                         /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               /
   /                        DATA + PADDING                         /
   /                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  public class DimeDelimitedInputStream extends java.io.FilterInputStream {
      protected static Log log =
          LogFactory.getLog(DimeDelimitedInputStream.class.getName());
  
      java.io.InputStream is = null; //The source input stream.
      boolean closed = true; //The stream has been closed.
      boolean theEnd = false; //There are no more streams left.
      boolean moreChunks = false; //More chunks are a coming!
      boolean MB = false;  //First part of the stream. MUST be SOAP.
      boolean ME = false;  //Last part of stream.
      DimeTypeNameFormat tnf = null;
      String type = null;
      String id = null;
      long    recordLength = 0L; //length of the record.
      long    bytesRead = 0; //How many bytes of the record have been read.
      int dataPadLength = 0; //How many pad bytes there are.
      private static byte[] trash = new byte[4];
      protected int streamNo = 0;
      protected IOException streamInError = null;
  
      protected static int streamCount = 0; //number of streams produced.
  
      protected synchronized static int newStreamNo() {
          log.debug(JavaUtils.getMessage("streamNo", "" + (streamCount + 1)));
          return ++streamCount;
      }
        
      static boolean isDebugEnabled = false;
  
      /**
       * Gets the next stream. From the previous using  new buffer reading size.
       * @return the dime delmited stream. Null if there are no more streams.
       */
      synchronized DimeDelimitedInputStream getNextStream() 
       throws IOException {
          if (null != streamInError) throw streamInError;
          if (theEnd) return null;
          if (bytesRead < recordLength || moreChunks) //Stream must be read in 
succession 
              throw new RuntimeException(JavaUtils.getMessage(
               "attach.dimeReadFullyError")); 
          dataPadLength -= readPad(dataPadLength);
  
          //Create an new dime stream  that comes after this one.
          return  new DimeDelimitedInputStream(this.is);
      }
  
      /**
       * Create a new dime stream;
       */
      DimeDelimitedInputStream(java.io.InputStream is) throws IOException {
          super(null); //we handle everything so this is not necessary, don't won't to 
hang on to a reference.
          isDebugEnabled = log.isDebugEnabled();
          streamNo = newStreamNo();
          closed = false;
          this.is = is;
          readHeader(false);
      }
  
      private final int readPad(final int  size) throws IOException {
          if (0 == size) return 0;
          int read = readFromStream(trash, 0, size);
  
          if (size != read) {
              streamInError = new IOException(JavaUtils.getMessage(
              "attach.dimeNotPaddedCorrectly")); 
              throw streamInError;
          }
          return read;
      }
  
      private final int readFromStream(final byte[] b) throws IOException {
          return readFromStream(b, 0, b.length);
      }
  
      private final int readFromStream(final byte[] b,
          final int start, final int length) 
          throws IOException {
  
          int br = 0;
          int brTotal = 0;
  
          do {
              try {
                  br = is.read(b, brTotal + start, length - brTotal);
              } catch (IOException e) {
                  streamInError = e;
                  throw e;
              };
              if (br > 0) brTotal += br;
          }
          while (br > -1 && brTotal < length);
  
          return brTotal != 0 ? brTotal : br;
      }
  
      /**
       * Get the id for this stream part. 
       * @return the id; 
       */
      public String getContentId() {
          return id;
      }
  
      /**
       * Read from the boundary delimited stream.
       * @param b is the array to read into.
       * @param off is the offset 
       * @return the number of bytes read. -1 if endof stream.
       */
      public DimeTypeNameFormat getDimeTypeNameFormat() {
          return tnf;
      }
  
      /**
       * get type. 
       * @param b is the array to read into.
       * @param off is the offset 
       * @return the number of bytes read. -1 if endof stream.
       */
  
      public String getType() {
          return type;
      }
  
      /**
       * Read from the boundary delimited stream.
       * @param b is the array to read into.
       * @param off is the offset 
       * @return the number of bytes read. -1 if endof stream.
       */
      public synchronized int read(byte[] b, final int off,
          final int len) throws IOException {
  
          if (closed) {
              dataPadLength -= readPad(dataPadLength);
              throw new IOException(JavaUtils.getMessage("streamClosed"));
          }
          return _read(b, off, len);
      }
       
      protected int _read(byte[] b, final int off, final int len)
          throws IOException {
          if (len < 0) throw new IllegalArgumentException
                  (JavaUtils.getMessage("attach.readLengthError", 
                   "" + len)); 
  
          if (off < 0) throw new IllegalArgumentException
                  (JavaUtils.getMessage("attach.readOffsetError", 
                   "" + off)); 
          if (b == null) throw new IllegalArgumentException
                  (JavaUtils.getMessage("attach.readArrayNullError")); 
          if (b.length < off + len) throw new IllegalArgumentException
                  (JavaUtils.getMessage("attach.readArraySizeError",
                          "" + b.length, "" + len, "" + off)); 
  
          if (null != streamInError) throw streamInError; 
  
          if (0 == len) return 0; //quick.
  
          if (bytesRead >= recordLength && !moreChunks) {
              dataPadLength -= readPad(dataPadLength);
              return -1;
          }
  
          int totalbytesread = 0;                                        
          int bytes2read = 0;
  
          do {
              if (bytesRead >= recordLength && moreChunks)
                readHeader(true);
  
              bytes2read = (int) Math.min(recordLength - bytesRead,
                          (long) len - totalbytesread);
              bytes2read = (int) Math.min(recordLength - bytesRead,
                          (long) len - totalbytesread);
              try {
                  bytes2read = is.read(b, off + totalbytesread,
                   bytes2read);
              } catch (IOException e) {
                  streamInError = e;
                  throw e;
              } 
  
              if (0 < bytes2read) {
                  totalbytesread += bytes2read;
                  bytesRead += bytes2read;
              }
  
          }
          while (bytes2read > -1 && totalbytesread < len &&
              (bytesRead < recordLength || moreChunks));
  
          if (0 > bytes2read) {
              if (moreChunks) {
                  streamInError = new IOException(JavaUtils.getMessage(
                                  "attach.DimeStreamError0"));
                  throw streamInError;
              }  
              if (bytesRead < recordLength) {
                  streamInError = new IOException(JavaUtils.getMessage
                              ("attach.DimeStreamError1", 
                                "" + (recordLength - bytesRead)));
                  throw streamInError;
              }  
              if (!ME) {
                  streamInError = new IOException(JavaUtils.getMessage(
                                  "attach.DimeStreamError0"));
                  throw streamInError;
              }  
              //in theory the last chunk of data should also have been padded, but 
lets be tolerant of that.
              dataPadLength = 0;
  
          } else if (bytesRead >= recordLength) {
              //get rid of pading. 
              try {
                  dataPadLength -= readPad(dataPadLength);
              } catch (IOException e) {
                  //in theory the last chunk of data should also have been padded, but 
lets be tolerant of that.
                  if (!ME) throw e;
                  else {
                      dataPadLength = 0; 
                      streamInError = null;
                  }  
              }
          }
  
          if (bytesRead >= recordLength && ME) {
              theEnd = true;
          }
  
          return totalbytesread >= 0 ? totalbytesread : -1;
      }
  
      void readHeader(boolean isChunk) throws IOException {
  
          bytesRead = 0; //How many bytes of the record have been read.
          if (isChunk) { 
              if (!moreChunks) throw new RuntimeException(
                          JavaUtils.getMessage("attach.DimeStreamError2"));
              dataPadLength -= readPad(dataPadLength); //Just incase it was left over.
          }
  
          byte[] header = new byte[12];
  
          if (header.length != readFromStream(header)) {
              streamInError = new IOException(JavaUtils.getMessage(
                              "attach.DimeStreamError3",
                                "" + header.length));
              throw streamInError;
          }
  
          //VERSION
          byte version = (byte) ((header[0] >>> 3) & 0x1f);
  
          if (version > DimeMultiPart.CURRENT_VERSION) {
              streamInError = new 
IOException(JavaUtils.getMessage("attach.DimeStreamError4",
                              "" + version,
                               "" + DimeMultiPart.CURRENT_VERSION));
              throw streamInError;
          }
  
          //B, E, C
          MB = 0 != (0x4 & header[0]);
          ME = 0 != (0x2 & header[0]);
          moreChunks = 0 != (0x1 & header[0]);
  
          //TYPE_T
          if (!isChunk)
              tnf = DimeTypeNameFormat.parseByte((byte) ((header[1] >>> 4) & (byte) 
0xf));
  
          //OPTIONS_LENGTH        
          int optionsLength =
              ((((int) header[2]) << 8) & 0xff00) | ((int) header[3]); 
  
          //ID_LENGTH          
          int idLength = 
              ((((int) header[4]) << 8) & 0xff00) | ((int) header[5]); 
  
          //TYPE_LENGTH         
          int typeLength = ((((int) header[6]) << 8) & 0xff00)
            | ((int) header[7]); 
  
          //DATA_LENGTH                          
          recordLength = ((((long) header[8]) << 24) & 0xff000000L) |
                  ((((long) header[9]) << 16) & 0xff0000L) |
                  ((((long) header[10]) << 8) & 0xff00L) |
                  ((long) header[11] & 0xffL);
  
          //OPTIONS + PADDING
  
          if (0 != optionsLength) {
              byte[] optBytes = new byte[optionsLength]; 
  
              if (optionsLength != readFromStream(optBytes)) {
                  streamInError = new IOException(JavaUtils.getMessage(
                                  "attach.DimeStreamError5",
                                   "" + optionsLength));
                  throw streamInError;
              } 
              optBytes = null; //Yup throw it away, don't know anything about options.
  
              int pad = DimeBodyPart.dimePadding(optionsLength); 
  
              if (pad != readFromStream(header, 0, pad)) {
                  streamInError = new IOException(
                   JavaUtils.getMessage("attach.DimeStreamError7"));
                  throw streamInError;
              }
          }
  
          // ID + PADDING 
          if (0 < idLength) {
              byte[] idBytes = new byte[ idLength]; 
  
              if (idLength != readFromStream(idBytes)) {
                  streamInError = new IOException(
                  JavaUtils.getMessage("attach.DimeStreamError8"));
                  throw streamInError;
              } 
              if (idLength != 0 && !isChunk) {
                  id = new String(idBytes);
              }
              int pad = DimeBodyPart.dimePadding(idLength); 
  
              if (pad != readFromStream(header, 0, pad)) {
                  streamInError = new IOException(JavaUtils.getMessage(
                  "attach.DimeStreamError9"));
                  throw streamInError;
              }
          }
  
          //TYPE + PADDING
          if (0 < typeLength) {
              byte[] typeBytes = new byte[typeLength]; 
  
              if (typeLength != readFromStream(typeBytes)) {
                  streamInError = new IOException(JavaUtils.getMessage(
                  "attach.DimeStreamError10"));
                  throw streamInError;
              } 
              if (typeLength != 0 && !isChunk) {
                  type = new String(typeBytes);
              }
              int pad = DimeBodyPart.dimePadding(typeLength); 
  
              if (pad != readFromStream(header, 0, pad)) {
                  streamInError = new IOException(JavaUtils.getMessage(
                  "attach.DimeStreamError11"));
  
                  throw streamInError;
              }
          }
          log.debug("MB:" + MB + ", ME:" + ME + ", CF:" + moreChunks +
              "Option length:" + optionsLength +
               ", ID length:" + idLength +
              ", typeLength:" + typeLength + ", TYPE_T:" + tnf);
          log.debug("id:\"" + id + "\"");
          log.debug("type:\"" + type + "\"");
          log.debug("recordlength:\"" + recordLength + "\"");
  
          dataPadLength = DimeBodyPart.dimePadding(recordLength);
      }
  
      /**
       * Read from the delimited stream.
       * @param b is the array to read into. Read as much as possible 
       *   into the size of this array.
       * @return the number of bytes read. -1 if endof stream.
       */
      public int read(byte[] b) throws IOException {
          return read(b, 0, b.length);
      }
  
      /**
       * Read from the boundary delimited stream.
       * @return The byte read, or -1 if endof stream.
       */
  
      public int read() throws IOException {
          byte[] b = new byte[1]; 
          int read = read(b, 0, 1);
  
          if (read < 0) return -1;
          else return b[0];
      }
  
      /**
       * Closes the stream.
       */
      public synchronized void close() throws IOException {
          if (closed) return;
          closed = true; //mark it closed.
          log.debug(JavaUtils.getMessage("bStreamClosed", "" + streamNo));
          if (bytesRead < recordLength || moreChunks) {
              //We need get this off the stream.
              //Easy way to flush through the stream;
              byte[] readrest = new byte[1024 * 16];
              int bread = 0;
  
              do {
                  bread = _read(readrest, 0, readrest.length);
              }
              while (bread > -1);
          }
          dataPadLength -= readPad(dataPadLength);
      }
  
      /**
       * mark the stream.
       * This is not supported.
       */
      public void mark(int readlimit) {//do nothing
      }
  
      /**
       * reset the stream.
       * This is not supported.
       */
      public void reset() throws IOException {
          streamInError = new IOException(JavaUtils.getMessage(
          "attach.bounday.mns"));
          throw streamInError;
      }
  
      /**
       * markSupported
       * return false; 
       */
      public boolean markSupported() {
          return false;
      }
  
      public synchronized int available() throws IOException {
          if (null != streamInError) throw streamInError;
          int chunkAvail = (int) Math.min((long)
          Integer.MAX_VALUE, recordLength - bytesRead);
  
          int streamAvail = 0;
  
          try {
              streamAvail = is.available();
          } catch (IOException e) {
              streamInError = e;
              throw e;
          };
  
          if (chunkAvail == 0 && moreChunks && (12 + dataPadLength)
            <= streamAvail) {
              dataPadLength -= readPad(dataPadLength);
              readHeader(true);
              return available();
          }
          return  Math.min(streamAvail, chunkAvail); 
      }
  }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/attachments/DimeMultiPart.java
  
  Index: DimeMultiPart.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * @author Rick Rineholt 
   */
  
  package org.apache.axis.attachments;
  
  
  import org.apache.axis.transport.http.HTTPConstants;
  import javax.activation.*;
  
  
  /**
   * This class hold all parts of a DIME multipart message. 
   */
  
  public final class DimeMultiPart {
      static final long transSize = Integer.MAX_VALUE;
      static final byte CURRENT_VERSION = 1; //Anything above this we don't support.
      protected java.util.Vector parts = new java.util.Vector(); 
      public DimeMultiPart() {};
      public void addBodyPart(DimeBodyPart part) {
          parts.add(part);
      }
  
      public void write(java.io.OutputStream os)
         throws java.io.IOException {
          int size = parts.size();
          int last = size - 1;
  
          for (int i = 0; i < size; ++i)
              ((DimeBodyPart) parts.elementAt(i)).write(os,
                  (byte) ((i == 0 ? DimeBodyPart.POSITION_FIRST : 
                   (byte) 0)
                      | (i == last ? DimeBodyPart.POSITION_LAST :
                       (byte) 0)), transSize);
      }
  
      public long getTransmissionSize() {
          long size = 0;
  
          for (int i = parts.size() - 1; i > -1; --i)
              size +=
              ((DimeBodyPart) parts.elementAt(i)).getTransmissionSize(
                transSize);
  
          return size;  
      }
  }
  
  
  
  1.1                  
xml-axis/java/src/org/apache/axis/attachments/DimeTypeNameFormat.java
  
  Index: DimeTypeNameFormat.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * @author Rick Rineholt 
   */
  
  package org.apache.axis.attachments;
  
  
  import org.apache.axis.transport.http.HTTPConstants;
  import javax.activation.*;
  import org.apache.axis.utils.JavaUtils;
  
  
  /**
   * This class is a single part for DIME mulitpart message. 
   */
  
  
  public final class DimeTypeNameFormat {
      private byte format = 0; 
      private DimeTypeNameFormat() {}; 
      private DimeTypeNameFormat(byte f) {
          format = f;
      }; 
      //Current type values.
      final static byte NOCHANGE_VALUE = 0x00; // indicates the type is unchanged from 
the previous record (used for chunking)
      final static byte MIME_VALUE = 0x01; //indicates the type is specified as a MIME 
media-type
      final static byte URI_VALUE = 0x02; // indicates the type is specified as an 
absolute URI
      final static byte UNKNOWN_VALUE = 0x03; // indicates the type is not specified
      final static byte NODATA_VALUE = 0x04; // indicates the record has no payload 
  
      static final DimeTypeNameFormat NOCHANGE =
        new DimeTypeNameFormat(NOCHANGE_VALUE);
  
      public static final DimeTypeNameFormat MIME=
        new DimeTypeNameFormat(MIME_VALUE);
  
      public static final DimeTypeNameFormat URI=
        new DimeTypeNameFormat(URI_VALUE);
  
      public static final DimeTypeNameFormat UNKNOWN=
        new DimeTypeNameFormat(UNKNOWN_VALUE);
  
      static final DimeTypeNameFormat NODATA=
        new DimeTypeNameFormat(NODATA_VALUE);
  
      private static String[] toEnglish = {"NOCHANGE", "MIME", "URI",
        "UNKNOWN", "NODATA"};
      private static DimeTypeNameFormat[] fromByte = {NOCHANGE, MIME,
        URI, UNKNOWN, NODATA};
  
      public final String toString() {
          return toEnglish[format];
      }
  
      public final byte toByte() {
          return format;
      }
  
      public final boolean equals(final Object x) {
          if (x == null) return false;
          if (!(x instanceof DimeTypeNameFormat)) return false;
          return ((DimeTypeNameFormat) x).format == this.format;
      }
  
      public static DimeTypeNameFormat parseByte(byte x) {
          if (x < 0 || x > fromByte.length)
              throw new IllegalArgumentException(JavaUtils.getMessage(
                          "attach.DimeStreamBadType", "" + x)); 
          return fromByte[x];
      }
  
      public static DimeTypeNameFormat parseByte(Byte x) {
          return parseByte(x.byteValue());
      }
  }
  
  
  
  1.1                  
xml-axis/java/src/org/apache/axis/attachments/MultiPartDimeInputStream.java
  
  Index: MultiPartDimeInputStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.attachments;
  
  
  import org.apache.axis.transport.http.HTTPConstants; 
  import org.apache.axis.attachments.ManagedMemoryDataSource;
  import javax.activation.DataHandler;
  import org.apache.axis.Part;
  import org.apache.axis.utils.JavaUtils;
  import javax.mail.internet.MimeUtility;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  
  /**
   *
   * @author Rick Rineholt 
   */
  
  /** This simulates the multipart stream 
   *
   */
  public class MultiPartDimeInputStream extends  MultiPartInputStream {
      protected static Log log =
          LogFactory.getLog(MultiPartDimeInputStream.class.getName());
  
      protected java.util.HashMap parts = new java.util.HashMap();
      protected java.util.LinkedList orderedParts = new java.util.LinkedList();
      protected int rootPartLength = 0;
      protected boolean closed = false; //If true the stream has been closed.
      protected boolean eos = false;  //This is set once the SOAP packet has reached 
the end of stream.
      //This stream controls and manages the  boundary.
      protected DimeDelimitedInputStream dimeDelimitedStream = null;
      protected java.io.InputStream soapStream = null; //Set the soap stream once 
found.
      protected byte[] boundary = null;
      protected java.io.ByteArrayInputStream cachedSOAPEnvelope = null; //Caches the 
soap stream if it is
      //Still open and a reference to read data in a later attachment occurs.
      protected String contentId = null; 
                
      /**
       * Multipart stream.
       * @param the string that holds the contentType
       * @param is the true input stream from where the source.
       */
      public MultiPartDimeInputStream (java.io.InputStream is)
        throws java.io.IOException {
          super(null); //don't cache this stream.
          soapStream = dimeDelimitedStream = new DimeDelimitedInputStream(is); //The 
Soap stream must always be first
          contentId = dimeDelimitedStream.getContentId();
      }
  
      public Part getAttachmentByReference(final String[] id)
        throws org.apache.axis.AxisFault {  // if CID should still have CID: prefix.  
          //First see if we have read it in yet.
          Part ret = null; 
  
          try {
              for (int i = id.length - 1; ret == null && i > -1; --i) {
                  ret = (AttachmentPart) parts.get(id[i]);
              }
  
              if (null == ret) {
                  ret = readTillFound(id);
              }
              log.debug(JavaUtils.getMessage("return02",
                      "getAttachmentByReference(\"" + id + "\"",
                      (ret == null ? "null" : ret.toString())));
          } catch (java.io.IOException e) {
              throw new org.apache.axis.AxisFault(e.getClass().getName()
                + e.getMessage());
          }
          return ret;
      }
  
      protected void addPart(String contentId, String locationId,
       AttachmentPart  ap) {
          if (contentId != null && contentId.trim().length() != 0) 
parts.put(contentId, ap);
          if (locationId != null && locationId.trim().length() != 
0)parts.put(locationId, ap);
          orderedParts.add(ap); 
      }
  
      protected final static String[] READ_ALL = { " * \0 ".intern()}; //Shouldn't 
never match
  
      protected void readAll() throws org.apache.axis.AxisFault {
          try {
              readTillFound(READ_ALL);
          } catch (Exception e) {
              throw org.apache.axis.AxisFault.makeFault(e);
          }
      }
  
      public java.util.Collection getAttachments() 
        throws org.apache.axis.AxisFault {
          readAll();
          return orderedParts; 
      }
  
      /** 
       * This will read streams in till the one that is needed is found.
       * @param The id is the stream being sought. TODO today its only handles CID. 
all ContentId streams
       *         should be prefixed by "cid:";
       */
  
      protected Part readTillFound(final String[] id) 
        throws java.io.IOException {
          if (dimeDelimitedStream == null) return null; //The whole stream has been 
consumed already
          Part ret = null;
  
          try {
  
              if (soapStream != null) { //Still on the SOAP stream.
                  if (!eos) { //The SOAP packet has not been fully read yet. Need to 
store it away.
  
                      java.io.ByteArrayOutputStream soapdata =
                        new java.io.ByteArrayOutputStream(1024 * 8);
  
                      byte[] buf = new byte[1024 * 16];
                      int byteread = 0;
  
                      do {
                          byteread = soapStream.read(buf);
                          if (byteread > 0) soapdata.write(buf, 0, 
                           byteread);
                      }
                      while (byteread > -1);
                      soapdata.close();
                      soapStream.close();
                      soapStream = new java.io.ByteArrayInputStream(
                       soapdata.toByteArray());
                  }
                  dimeDelimitedStream = dimeDelimitedStream.getNextStream();
              }
              //Now start searching for the data.
  
              if (null != dimeDelimitedStream) {
                  do {
                      String contentId = dimeDelimitedStream.getContentId();
                      String type = dimeDelimitedStream.getType();
  
                      if (type != null && 
!dimeDelimitedStream.getDimeTypeNameFormat().equals(DimeTypeNameFormat.MIME)) {
                          type = "application/uri; uri=\"" + type + "\"";
                      }
                        
                      DataHandler dh = new DataHandler(
                        new ManagedMemoryDataSource(dimeDelimitedStream,
                        1024, type, true));
  
                      AttachmentPart ap = new AttachmentPart(dh);
  
                      if (contentId != null) 
                          ap.addMimeHeader(HTTPConstants.HEADER_CONTENT_ID, 
contentId); 
  
                      addPart(contentId, "", ap);
  
                      for (int i = id.length - 1; ret == null && i > -1; --i) {
                          if (contentId != null && id[i].equals(contentId)) { //This 
is the part being sought
                              ret = ap;
                          }
                      }     
  
                      dimeDelimitedStream = 
                       dimeDelimitedStream.getNextStream();
  
                  }
                  while (null == ret && null != dimeDelimitedStream);
              }
          } catch (Exception e) {
              throw org.apache.axis.AxisFault.makeFault(e);
          }
  
          return ret;
      }
  
      /**
       * Return the content location. 
       * @return the Content-Location of the stream.
       *   Null if no content-location specified.
       */
      public String getContentLocation() {
          return null;
      }
  
      /**
       * Return the content id of the stream 
       * @return the Content-Location of the stream.
       *   Null if no content-location specified.
       */
      public String getContentId() {
          return contentId;
      }
  
      /**
       * Read the root stream. 
       */
  
      public int read(byte[] b, int off, int len)
        throws java.io.IOException {
          if (closed) {
              throw new java.io.IOException(JavaUtils.getMessage(
                "streamClosed"));
          }
          if (eos) {
              return -1;
          }
          int read = soapStream.read(b, off, len);
  
          if (read < 0) {
              eos = true;
          }
          return read;
      }
  
      public int read(byte[] b) throws java.io.IOException {
          return read(b, 0, b.length);
      }
  
      public int read() throws java.io.IOException {
          if (closed) {
              throw new java.io.IOException(JavaUtils.getMessage(
              "streamClosed"));
          }
          if (eos) {
              return -1;
          }
          int ret = soapStream.read();
  
          if (ret < 0) {
              eos = true;
          }
          return ret;
      }
  
      public void close() throws java.io.IOException {
          closed = true;
          soapStream.close();
      }
  }
  
  
  
  1.1                  
xml-axis/java/src/org/apache/axis/attachments/MultiPartInputStream.java
  
  Index: MultiPartInputStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.axis.attachments;
  
  
  import org.apache.axis.transport.http.HTTPConstants; 
  import org.apache.axis.attachments.ManagedMemoryDataSource;
  import javax.activation.DataHandler;
  import org.apache.axis.Part;
  import org.apache.axis.utils.JavaUtils;
  import javax.mail.internet.MimeUtility;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  
  /**
   *
   * @author Rick Rineholt 
   */
  
  /** This simulates the multipart stream 
   *
   */
  public abstract class MultiPartInputStream extends
    java.io.FilterInputStream {
  
      MultiPartInputStream(java.io.InputStream is) {
          super(is);
      }
  
      public abstract Part getAttachmentByReference(final String[] id)
       throws org.apache.axis.AxisFault;  // if CID should still have CID: prefix.  
  
      public abstract java.util.Collection getAttachments() 
        throws org.apache.axis.AxisFault;
  
      /**
       * Return the content location. 
       * @return the Content-Location of the stream.
       *   Null if no content-location specified.
       */
      public abstract String getContentLocation();
  
      /**
       * Return the content id of the stream 
       * @return the Content-Location of the stream.
       *   Null if no content-location specified.
       */
      public abstract String getContentId();
  
  }
  
  
  
  1.151     +48 -0     xml-axis/java/src/org/apache/axis/client/Call.java
  
  Index: Call.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/client/Call.java,v
  retrieving revision 1.150
  retrieving revision 1.151
  diff -u -r1.150 -r1.151
  --- Call.java 29 Jun 2002 17:42:19 -0000      1.150
  +++ Call.java 30 Jun 2002 19:59:04 -0000      1.151
  @@ -132,6 +132,7 @@
    *     SEND_TYPE_ATTR - Should we send the XSI type attributes (true/false)
    *     TIMEOUT        - Timeout used by transport sender in seconds
    *     TRANSPORT_NAME - Name of transport handler to use
  + *     ATTACHMENT_ENCAPSULATION_FORMAT- Send attachments as MIME the default, or 
DIME. 
    * </pre>
    *
    * @author Doug Davis ([EMAIL PROTECTED])
  @@ -198,6 +199,22 @@
       public static final boolean FAULT_ON_NO_RESPONSE = false;
   
       /**
  +     * Property for setting attachment format.
  +     */
  +    public static final String ATTACHMENT_ENCAPSULATION_FORMAT=
  +      "attachment_encapsulation_format";
  +    /**
  +     * Property value for setting attachment format as MIME.
  +     */
  +    public static final String ATTACHMENT_ENCAPSULATION_FORMAT_MIME=
  +      "axis.attachment.style.mime";
  +    /**
  +     * Property value for setting attachment format as DIME.
  +     */
  +    public static final String ATTACHMENT_ENCAPSULATION_FORMAT_DIME=
  +      "axis.attachment.style.dime";
  +
  +    /**
        * A Hashtable mapping protocols (Strings) to Transports (classes)
        */
       private static Hashtable transports  = new Hashtable();
  @@ -350,6 +367,19 @@
               if (transport != null)
                   transport.setTransportName((String) value);
           }
  +        else if ( name.equals(ATTACHMENT_ENCAPSULATION_FORMAT) ) {
  +            if (!(value instanceof String)) {
  +                throw new IllegalArgumentException(
  +                        JavaUtils.getMessage("badProp00", new String[] {
  +                        name, "java.lang.String", value.getClass().getName()}));
  +            }
  +            if(!value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME ) && 
  +               !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME ))
  +                throw new IllegalArgumentException(
  +                        JavaUtils.getMessage("badattachmenttypeerr", new String[] {
  +                        (String) value, ATTACHMENT_ENCAPSULATION_FORMAT_MIME + " "
  +                        +ATTACHMENT_ENCAPSULATION_FORMAT_DIME  }));
  +        }
           else {
               throw new IllegalArgumentException(
                       JavaUtils.getMessage("badProp05", name));
  @@ -410,11 +440,13 @@
           propertyNames.add(USERNAME_PROPERTY);
           propertyNames.add(PASSWORD_PROPERTY);
           propertyNames.add(SESSION_MAINTAIN_PROPERTY);
  +        propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT);
           propertyNames.add(OPERATION_STYLE_PROPERTY);
           propertyNames.add(SOAPACTION_USE_PROPERTY);
           propertyNames.add(SOAPACTION_URI_PROPERTY);
           propertyNames.add(ENCODINGSTYLE_URI_PROPERTY);
           propertyNames.add(TRANSPORT_NAME);
  +            propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT);
       }
   
       public Iterator getPropertyNames() {
  @@ -1483,6 +1515,22 @@
        * @param msg the new request message.
        */
       public void setRequestMessage(Message msg) {
  +         String attachformat= (String)getProperty(
  +           ATTACHMENT_ENCAPSULATION_FORMAT);
  +
  +         if(null != attachformat){
  +              org.apache.axis.attachments.Attachments attachments=
  +                msg.getAttachmentsImpl();
  +              if(null != attachments) {
  +                  if( null != attachformat && attachformat.equals(
  +                    ATTACHMENT_ENCAPSULATION_FORMAT_MIME)) 
  +                    attachments.setSendType(attachments.SEND_TYPE_MIME);
  +                  else if( null != attachformat && attachformat.equals(
  +                      ATTACHMENT_ENCAPSULATION_FORMAT_DIME)) {
  +                    attachments.setSendType(attachments.SEND_TYPE_DIME);
  +                  }
  +              }
  +         }
   
           if(null != attachmentParts && !attachmentParts.isEmpty()){
               try{
  
  
  
  1.120     +1 -1      
xml-axis/java/src/org/apache/axis/transport/http/AxisServlet.java
  
  Index: AxisServlet.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/transport/http/AxisServlet.java,v
  retrieving revision 1.119
  retrieving revision 1.120
  diff -u -r1.119 -r1.120
  --- AxisServlet.java  27 Jun 2002 22:44:13 -0000      1.119
  +++ AxisServlet.java  30 Jun 2002 19:59:04 -0000      1.120
  @@ -643,7 +643,7 @@
               res.setStatus(HttpServletResponse.SC_NO_CONTENT);
               if(isDebug) log.debug("NO AXIS MESSAGE TO RETURN!");
               //String resp = JavaUtils.getMessage("noData00");
  -            //res.setContentLength(resp.getBytes().length);
  +            //res.setContentLength((int) resp.getBytes().length);
               //res.getWriter().print(resp);
           } else {
               if(isDebug) {
  
  
  
  1.53      +9 -0      xml-axis/java/src/org/apache/axis/utils/JavaUtils.java
  
  Index: JavaUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/JavaUtils.java,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -r1.52 -r1.53
  --- JavaUtils.java    28 Jun 2002 06:17:54 -0000      1.52
  +++ JavaUtils.java    30 Jun 2002 19:59:04 -0000      1.53
  @@ -720,6 +720,15 @@
       } // getMessage
   
       /**
  +     * Get the message with the given key.  If arguments are specified in the 
message (in the
  +     * format of "{0} {1}") then fill them in with the values of var1 and var2, 
respectively.
  +     */
  +    public static String getMessage(String key, String var1, String var2, String 
var3)
  +            throws MissingResourceException {
  +        return MessageFormat.format(getMessage(key), new String[]{var1, var2, 
var3});
  +    } // getMessage
  +
  +    /**
        * Get the message with the given key.  Replace each "{X}" in the message with 
vars[X].  If
        * there are more vars than {X}'s, then the extra vars are ignored.  If there 
are more {X}'s
        * than vars, then a java.text.ParseException (subclass of RuntimeException) is 
thrown.
  
  
  
  1.20      +26 -0     xml-axis/java/src/org/apache/axis/utils/axisNLS.properties
  
  Index: axisNLS.properties
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/axisNLS.properties,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- axisNLS.properties        29 Jun 2002 18:05:19 -0000      1.19
  +++ axisNLS.properties        30 Jun 2002 19:59:04 -0000      1.20
  @@ -909,4 +909,30 @@
   optionNoWrap00=turn off support for "wrapped" document/literal
   noTypeOrElement00=Error: Message part {0} of operation or fault {1} has no element 
or type attribute.
   
  +msgContentLengthHTTPerr=Message content length {0} exceeds servlet return capacity.
  +badattachmenttypeerr=The value of {0} for attachment format must be {1};
  +attach.dimetypeexceedsmax=DIME Type length is {0} which exceeds maximum {0}
  +attach.dimelengthexceedsmax=DIME ID length is {0} which exceeds maximum {1}.
  +attach.dimeMaxChunkSize0=Max chunk size \"{0}\" needs to be greater than one.
  +attach.dimeMaxChunkSize1=Max chunk size \"{0}\" exceeds 32 bits.
  +attach.dimeReadFullyError=Each DIME Stream must be read fully or closed in 
succession.
  +attach.dimeNotPaddedCorrectly=DIME stream data not padded correctly.
  +attach.readLengthError=Received \"{0}\" bytes to read.
  +attach.readOffsetError=Received \"{0}\" as an offset.
  +attach.readArrayNullError=Array to read is null
  +attach.readArrayNullError=Array to read is null
  +attach.readArraySizeError=Array size of {0} to read {1} at offset {2} is too small.
  +attach.DimeStreamError0=End of physical stream detected when more DIME chunks 
expected.
  +attach.DimeStreamError1=End of physical stream detected when {0} more bytes 
expected.
  +attach.DimeStreamError2=There are no more DIME chunks expected!
  +attach.DimeStreamError3=DIME header less than {0} bytes.
  +attach.DimeStreamError4=DIME version received \"{0}\" greater than current 
supported version \"{1}\".
  +attach.DimeStreamError5=DIME option length \"{0}\" is greater stream length.
  +attach.DimeStreamError6=DIME typelength length \"{0}\" is greater stream length.
  +attach.DimeStreamError7=DIME stream closed during options padding. 
  +attach.DimeStreamError8=DIME stream closed getting ID length.
  +attach.DimeStreamError9=DIME stream closed getting ID padding.
  +attach.DimeStreamError10=DIME stream closed getting type.
  +attach.DimeStreamError11=DIME stream closed getting type padding.
  +attach.DimeStreamBadType=DIME stream received bad type \"{0}\".
   
  
  
  


Reply via email to