rineholt 02/02/27 05:06:12 Modified: java/src/org/apache/axis Message.java Part.java SOAPPart.java java/src/org/apache/axis/attachments AttachmentPart.java Attachments.java AttachmentsImpl.java MimeUtils.java Log: Changes supplied by Taras Shkvarchuk <[EMAIL PROTECTED]>" Revision Changes Path 1.64 +21 -5 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.63 retrieving revision 1.64 diff -u -r1.63 -r1.64 --- Message.java 25 Feb 2002 17:38:14 -0000 1.63 +++ Message.java 27 Feb 2002 13:06:11 -0000 1.64 @@ -91,6 +91,12 @@ // NOT SUPPORTED NOW public static final String MIME_APPLICATION_DIME = "application/dime"; + /** Default Attachments Implementation class */ + public static final String DEFAULT_ATTACHMNET_IMPL="org.apache.axis.attachments.AttachmentsImpl"; + + /** Current Attachment implementation */ + private static String mAttachmentsImplClassName=DEFAULT_ATTACHMNET_IMPL; + // look at the input stream to find the headers to decide. public static final String MIME_UNKNOWN = " "; @@ -110,9 +116,15 @@ */ private Attachments mAttachments = null; - /** - * The MessageContext we are associated with. - */ + /** + * Returns name of the class prividing Attachment Implementation + * @returns class Name + */ + public static String getAttachmentImplClassName(){ + return mAttachmentsImplClassName; + } + + private MessageContext msgContext; public String getMessageType() { @@ -244,7 +256,7 @@ Constructor attachImplConstr = attachImpl.getConstructors()[0]; try { mAttachments = (Attachments) attachImplConstr.newInstance( - new Object[] { this, initialContents, + new Object[] { initialContents, contentType, contentLocation}); //If it can't support it, it wont have a root part. @@ -264,11 +276,15 @@ } } - // The stream was not determined by a more complex type so default to // text/xml if (null == mSOAPPart) { mSOAPPart = new SOAPPart(this, initialContents, bodyInStream); } + else + mSOAPPart.setMessage(this); + + // The stream was not determined by a more complex type so default to + if(mAttachments!=null) mAttachments.setRootPart(mSOAPPart); } /** 1.6 +14 -17 xml-axis/java/src/org/apache/axis/Part.java Index: Part.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/Part.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- Part.java 22 Feb 2002 23:39:43 -0000 1.5 +++ Part.java 27 Feb 2002 13:06:11 -0000 1.6 @@ -86,7 +86,6 @@ protected static Log log = LogFactory.getLog(Part.class.getName()); - private Message msg; private Hashtable headers = new Hashtable(); private String contentId; private String contentLocation; @@ -95,8 +94,7 @@ * Fill in the Message field. (Of course this can only be called by * subclass constructors since Part itself is abstract.) */ - public Part (Message parent) { - msg = parent; + public Part () { addMimeHeader(HTTPConstants.HEADER_CONTENT_ID , getNewContentIdValue()); } @@ -128,20 +126,6 @@ } /** - * Get the Message for this Part. - */ - public Message getMessage () { - return msg; - } - - /** - * Set the Message for this Part. - */ - public void setMessage (Message msg) { - this.msg= msg; - } - - /** * Total size in bytes (of all content and headers, as encoded). public abstract int getSize(); */ @@ -159,6 +143,19 @@ public void setContentLocation(String loc) { addMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION, loc); } + + /** + * Sets Content-Id of this part. "cid:" prefix will be added if one wan't + * already defined. + * @param newCid new Content-Id + * @returns void + */ + public void setContentId(String newCid){ + if(!newCid.toLowerCase().startsWith("cid:")){ + newCid="cid:"+newCid; + } + addMimeHeader(HTTPConstants.HEADER_CONTENT_ID,newCid); + } /** * Content ID. 1.14 +25 -2 xml-axis/java/src/org/apache/axis/SOAPPart.java Index: SOAPPart.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/SOAPPart.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- SOAPPart.java 25 Feb 2002 17:38:14 -0000 1.13 +++ SOAPPart.java 27 Feb 2002 13:06:11 -0000 1.14 @@ -116,6 +116,11 @@ private Object currentMessage ; /** + * Message object this part is tied to. Used for serialization settings. + */ + private Message msgObject; + + /** * The original message. Again, may be String, byte[], InputStream, * or SOAPEnvelope. */ @@ -127,7 +132,8 @@ * "Just something to us working..." */ public SOAPPart(Message parent, Object initialContents, boolean isBodyStream) { - super(parent); + super(); + msgObject=parent; originalMessage = initialContents; int form = FORM_STRING; if (initialContents instanceof SOAPEnvelope) { @@ -151,6 +157,22 @@ } */ + + /** + * Get the Message for this Part. + */ + public Message getMessage(){ + return msgObject; + } + + /** + * Set the Message for this Part. + * Do not call this Directly. Called by Message. + */ + public void setMessage (Message msg) { + this.msgObject= msg; + } + /** * Content type is always "text/xml" for SOAPParts. */ @@ -236,7 +258,7 @@ * array. This will force buffering of the message. */ public byte[] getAsBytes() { - log.debug( "Enter: SOAPPart::getAsBytes" ); + log.debug( "Enter: SOAPPart::getAsBytes" ); if ( currentForm == FORM_BYTES ) { log.debug( "Exit: SOAPPart::getAsBytes" ); return (byte[])currentMessage; @@ -300,6 +322,7 @@ log.debug( "Exit: SOAPPart::getAsBytes" ); return null; + } /** 1.6 +3 -18 xml-axis/java/src/org/apache/axis/attachments/AttachmentPart.java Index: AttachmentPart.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/attachments/AttachmentPart.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- AttachmentPart.java 22 Feb 2002 23:39:43 -0000 1.5 +++ AttachmentPart.java 27 Feb 2002 13:06:11 -0000 1.6 @@ -87,33 +87,18 @@ javax.activation.DataHandler datahandler= null; - /** - * Do not call this directly! This should only be called by the - * AttachmentsImpl object. - */ - - - public AttachmentPart(Message parent) { - super(parent); - } - - public AttachmentPart(Message parent, javax.activation.DataHandler dh ) { - super(parent); - datahandler= dh; - addMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE , dh.getContentType()); - } public AttachmentPart() { - super(null); + super(); } public AttachmentPart(javax.activation.DataHandler dh ) { - super(null); + super(); datahandler= dh; addMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE , dh.getContentType()); } - javax.activation.DataHandler getActiviationDataHandler(){ + public javax.activation.DataHandler getActiviationDataHandler(){ return datahandler; } 1.6 +23 -0 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.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- Attachments.java 26 Nov 2001 19:09:31 -0000 1.5 +++ Attachments.java 27 Feb 2002 13:06:11 -0000 1.6 @@ -71,6 +71,24 @@ public interface Attachments { /** + * Adds an existing attachment to this list. + * Note: Passed part will be bound to this message. + * @param newPart new part to add + * @returns Part old attachment with the same Content-ID, or null. + * @throws org.apache.axis.AxisFault + */ + public Part addAttachmentPart(Part newPart) throws org.apache.axis.AxisFault; + + /** + * This method uses getAttacmentByReference() to look for attachment. + * If attachment has been found, it will be removed from the list, and + * returned to the user. + * @param The reference that referers to an attachment. + * @return The part associated with the removed attachment, or null. + */ + public Part removeAttachmentPart(String reference) throws org.apache.axis.AxisFault; + + /** * This method should look at a refernce and determine if it is a CID: or url * to look for attachment. * @param The reference in the xml that referers to an attachment. @@ -103,6 +121,11 @@ * otherwise null. */ public Part getRootPart(); + + /** + * Sets the root part of this multipart block + */ + public void setRootPart(Part newRoot); /** * Get the content length of the stream. 1.12 +101 -35 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.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- AttachmentsImpl.java 7 Dec 2001 19:48:53 -0000 1.11 +++ AttachmentsImpl.java 27 Feb 2002 13:06:11 -0000 1.12 @@ -61,9 +61,11 @@ import org.apache.axis.AxisFault; import org.apache.axis.Message; import org.apache.axis.Part; +import org.apache.axis.SOAPPart; import javax.activation.DataHandler; import javax.activation.DataSource; +import java.util.*; /** * Implements the Attachment interface, via an actual Hashmap of actual @@ -71,9 +73,9 @@ */ public class AttachmentsImpl implements Attachments { - private Message msg; - private java.util.HashMap attachments = new java.util.HashMap(); - protected org.apache.axis.SOAPPart soapPart = null; + private HashMap attachments = new java.util.HashMap(); + private LinkedList orderedAttachments=new LinkedList(); + protected SOAPPart soapPart = null; /** * The actual stream to manage the multi-related input stream. */ @@ -88,14 +90,12 @@ /** * Construct one of these on a parent Message. * Should only ever be called by Message constructor! - * @param msg the message associated * @param initialContents should be anything but today only a stream is * supported. * @param The mime content type of the stream for transports that provide * it. */ - public AttachmentsImpl(Message msg, - Object intialContents, + public AttachmentsImpl(Object intialContents, String contentType, String contentLocation) throws org.apache.axis.AxisFault @@ -106,7 +106,6 @@ } this.contentLocation = contentLocation; - this.msg = msg; if (contentType != null) { if (contentType.equals(org.apache.axis.Message.MIME_UNKNOWN)) { //Process the input stream for headers to determine the mime @@ -134,7 +133,7 @@ } } - soapPart = new org.apache.axis.SOAPPart(msg, + soapPart = new org.apache.axis.SOAPPart(null, mpartStream, false); } else if (mimetype.equalsIgnoreCase(org.apache.axis.Message.MIME_APPLICATION_DIME)) { //do nothing today. @@ -146,19 +145,69 @@ } /** + * Copies attachment references from the multipartStream to local list. + * Done only once per object creation. + */ + private void mergeinAttachments() throws AxisFault{ + if(mpartStream!=null){ + Collection atts=mpartStream.getAttachments(); + mpartStream=null; + setAttachmentParts(atts); + } + } + + /** + * This method uses getAttacmentByReference() to look for attachment. + * If attachment has been found, it will be removed from the list, and + * returned to the user. + * @param The reference that referers to an attachment. + * @return The part associated with the removed attachment, or null. + */ + public Part removeAttachmentPart(String reference) throws org.apache.axis.AxisFault{ + mergeinAttachments(); + Part removedPart=getAttachmentByReference(reference); + if(removedPart!=null){ + attachments.remove(removedPart.getContentId()); + attachments.remove(removedPart.getContentLocation()); + orderedAttachments.remove(removedPart); + } + return removedPart; + } + + /** + * Adds an existing attachment to this list. + * Note: Passed part will be bound to this message. + * @param newPart new part to add + * @returns Part old attachment with the same Content-ID, or null. + */ + public Part addAttachmentPart(Part newPart) throws org.apache.axis.AxisFault{ + mergeinAttachments(); + Part oldPart=(Part)attachments.put(newPart.getContentId(),newPart); + if(oldPart!=null){ + orderedAttachments.remove(oldPart); + attachments.remove(oldPart.getContentLocation()); + } + orderedAttachments.add(newPart); + if(newPart.getContentLocation()!=null){ + attachments.put(newPart.getContentLocation(),newPart); + } + return oldPart; + } + + /** * Create an attachment part with a buried JAF data handler. */ public Part createAttachmentPart(Object datahandler) throws org.apache.axis.AxisFault { + mergeinAttachments(); if (!(datahandler instanceof javax.activation.DataHandler)) { throw new org.apache.axis.AxisFault("Unsupported attachment type \"" + datahandler.getClass().getName() + "\" only supporting \"" + javax.activation.DataHandler.class.getName() + "\"."); } - Part ret = new AttachmentPart(msg, - (javax.activation.DataHandler)datahandler); - attachments.put(ret.getContentId(), ret); + Part ret = new AttachmentPart((javax.activation.DataHandler)datahandler); + addAttachmentPart(ret); return ret; } @@ -167,13 +216,14 @@ */ public void setAttachmentParts(java.util.Collection parts) throws org.apache.axis.AxisFault { + mergeinAttachments(); attachments.clear(); + orderedAttachments.clear(); if (parts != null && !parts.isEmpty()) { for (java.util.Iterator i = parts.iterator(); i.hasNext();) { Part part = (Part) i.next(); if (null != part) { - part.setMessage(msg); - attachments.put(part.getContentId(), part); + addAttachmentPart(part); } } } @@ -182,16 +232,24 @@ /** * This method should look at a refernce and determine if it is a CID: or * url to look for attachment. + * <br> + * Note: if Content-Id or Content-Location headers have changed by outside + * code, lookup will not return proper values. In order to change these + * values attachment should be removed, then added again. * @param The reference in the xml that referers to an attachment. * @return The part associated with the attachment. */ public Part getAttachmentByReference(String reference) throws org.apache.axis.AxisFault { + mergeinAttachments(); if (null == reference) return null; reference = reference.trim(); if (0 == reference.length()) return null; - String[] id = null; + Part ret = (Part) attachments.get(reference); + if(ret!=null) + return ret; + String referenceLC = reference.toLowerCase(); if (!referenceLC.startsWith("cid:") && null != contentLocation) { String fqreference = contentLocation; @@ -200,14 +258,8 @@ fqreference += reference.substring(1); else fqreference += reference; - id = new String[]{reference, fqreference}; - } else { - id = new String[]{reference}; - } - Part ret = (AttachmentPart) attachments.get(id); - if (ret == null && mpartStream != null) { - //We need to still check if this coming in the input stream; - ret = mpartStream.getAttachmentByReference(id); + //lets see if we can get it as Content-Location + ret = (AttachmentPart) attachments.get(fqreference); } return ret; } @@ -219,16 +271,10 @@ */ public java.util.Collection getAttachments() throws org.apache.axis.AxisFault { - java.util.Collection ret = new java.util.LinkedList(); - - if (null != mpartStream) { - java.util.Collection mc = mpartStream.getAttachments(); - ret = new java.util.LinkedList(mc); // make a copy. + mergeinAttachments(); + return new LinkedList(orderedAttachments); } - return ret; - } - /** * From the complex stream return the root part. * Today this is SOAP. @@ -237,15 +283,29 @@ return soapPart; } + /** + * Sets the root part of this multipart block + */ + public void setRootPart(Part newRoot){ + try{ + this.soapPart=(SOAPPart)newRoot; + }catch(ClassCastException e){ + throw new ClassCastException("This attachment implementation "+ + "accepts only SOAPPart objects as root part."); + } + } + + public javax.mail.internet.MimeMultipart multipart = null; /** * Get the content length of the stream. */ public int getContentLength() throws org.apache.axis.AxisFault { + mergeinAttachments(); try { return (int)org.apache.axis.attachments.MimeUtils.getContentLength( - multipart != null ? multipart : (multipart = org.apache.axis.attachments.MimeUtils.createMP(msg.getSOAPPart().getAsString(), attachments))); + multipart != null ? multipart : (multipart = org.apache.axis.attachments.MimeUtils.createMP(soapPart.getAsString(), orderedAttachments))); } catch (Exception e) { throw AxisFault.makeFault(e); } @@ -256,9 +316,10 @@ */ public void writeContentToStream(java.io.OutputStream os) throws org.apache.axis.AxisFault { + mergeinAttachments(); org.apache.axis.attachments.MimeUtils.writeToMultiPartStream(os, multipart != null ? multipart : - (multipart = org.apache.axis.attachments.MimeUtils.createMP(msg.getSOAPPart().getAsString(), attachments))); - for( java.util.Iterator i= attachments.values().iterator(); i.hasNext(); ){ + (multipart = org.apache.axis.attachments.MimeUtils.createMP(soapPart.getAsString(), orderedAttachments))); + for( java.util.Iterator i= orderedAttachments.iterator(); i.hasNext(); ){ AttachmentPart part= (AttachmentPart)i.next(); DataHandler dh= AttachmentUtils.getActiviationDataHandler(part); DataSource ds= dh.getDataSource(); @@ -272,15 +333,20 @@ * Gets the content type for the whole stream. */ public String getContentType() throws org.apache.axis.AxisFault { + mergeinAttachments(); return org.apache.axis.attachments.MimeUtils.getContentType(multipart != null ? multipart : - (multipart = org.apache.axis.attachments.MimeUtils.createMP(msg.getSOAPPart().getAsString(), attachments))); + (multipart = org.apache.axis.attachments.MimeUtils.createMP(soapPart.getAsString(), orderedAttachments))); } /** *This is the number of attachments. **/ public int getAttachmentCount() { - return attachments.size(); + try{ + mergeinAttachments(); + return orderedAttachments.size(); + }catch(AxisFault e){} + return 0; } /** 1.11 +5 -7 xml-axis/java/src/org/apache/axis/attachments/MimeUtils.java Index: MimeUtils.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/attachments/MimeUtils.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- MimeUtils.java 25 Feb 2002 17:38:14 -0000 1.10 +++ MimeUtils.java 27 Feb 2002 13:06:11 -0000 1.11 @@ -230,10 +230,10 @@ /** * This routine will create a multipar object from the parts and the SOAP content. * @param the env should be the text for the main root part. - * @param the parts contain a collection of mappings of cids to the message parts. + * @param the parts contain a collection of the message parts. */ - public static javax.mail.internet.MimeMultipart createMP(String env, java.util.Map parts ) throws org.apache.axis.AxisFault { + public static javax.mail.internet.MimeMultipart createMP(String env, java.util.Collection parts ) throws org.apache.axis.AxisFault { javax.mail.internet.MimeMultipart multipart = null; try { @@ -250,14 +250,12 @@ messageBodyPart.setHeader(HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING, "binary"); multipart.addBodyPart(messageBodyPart); - java.util.Set pe = parts.entrySet(); - for (java.util.Iterator it = pe.iterator(); it.hasNext(); ) { - java.util.Map.Entry es = (java.util.Map.Entry) it.next(); - org.apache.axis.Part part= (org.apache.axis.Part) es.getValue(); + for (java.util.Iterator it = parts.iterator(); it.hasNext(); ) { + org.apache.axis.Part part= (org.apache.axis.Part) it.next(); javax.activation.DataHandler dh = org.apache.axis.attachments.AttachmentUtils.getActiviationDataHandler(part); - String contentID = (String) es.getKey(); + String contentID = part.getContentId(); if (contentID.startsWith("cid:")) contentID = contentID.substring(4);