I have a spot of code I would like to contribute to the group.  This
class I developed can be used to detach or attach any file sent over
web services.
This class is intended for use on the server side, and will need just
a little massaging to work in your environment.

It took me several painstaking hours to get AXIS to send an attachment
to a requesting .NET client, and for .NET to send an attachment to a
listening AXIS server.  With the help of the Steve Loughran article
"Fear of Attachments", and not a little of his code (thanks Steve!), I
was able to get .NET clients to utilize files stored on my AXIS web
server.

Please forgive the Exception handling.

To read Steve Loughran's article I referred to, ref:
http://www.mail-archive.com/axis-user@xml.apache.org/msg08732.html

Regards,
John Walker

johnwalker00 at gmail dot com
package ws.attachments;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.soap.AttachmentPart;

import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.attachments.Attachments;
import org.apache.axis.attachments.AttachmentsImpl;
import org.apache.log4j.Logger;

/**
 * This class can be used from within any AXIS web service method
 * 
 * @author jwalker
 */
public class AttachmentTrundler
{
	private static final Logger _logger = Logger.getLogger(AttachmentTrundler.class);

	public AttachmentTrundler()
	{
	}

	/**
	 * Attaches the file to the outgoing response message as DIME attachment.
	 * This attachment should be consumable by all .NET web service 
	 * clients.  The clients we are using are auto-generated proxy classes
	 * that have no knowledge of the attachment coming.  The WSDL will not 
	 * contain this information. 
	 * 
	 * @param fileName The full name of the file on the local filesystem to 
	 * 	send to the client requesting file attachment
	 * @return true, indicating attachment was successful.
	 * 
	 * @throws AttachmentException
	 */
	public boolean attachFile(File file) throws AttachmentException
	{
		try
		{
			MessageContext msgContext = MessageContext.getCurrentContext();
			Message resMsg = msgContext.getResponseMessage();
			
			//Get the file from the filesystem
			FileDataSource fileDS = new FileDataSource(file);
			DataHandler handler = new DataHandler(fileDS);
			
			//Create the attachment as a DIME attachment
			AttachmentPart attachment = resMsg.createAttachmentPart();
			resMsg.getAttachmentsImpl().setSendType(AttachmentsImpl.SEND_TYPE_DIME);
			attachment.setDataHandler(handler);
			
			//You can set the content type to be anything you wish. All my files are zips
			attachment.setContentType("zip");
			
			resMsg.addAttachmentPart(attachment);

		}catch (Exception e)
		{
			//I know some will argue about the wisdom of catching Exception, and then
			// throwing AttachmentException, and they would probably be right.  
			
			_logger.error("attachFile(File file = " + file + ")", e);

			throw new AttachmentException("There was a problem attaching the file to the web service call", e);
		}
		return true;
	}

	/**
	 * This method receives the DIME encoded attachment from the client and
	 * saves it on the server.
	 * 
	 * @param filename as the name to save the file on the server
	 * @return a java.io.File that represents the object on the file system
	 * 
	 * @throws AttachmentException This exception is thrown if anything 
	 * 	goes wrong within the detachment process.
	 */
	public File detachFile(String filename) throws AttachmentException
	{
		InputStream is = null;
		FileOutputStream os = null;
		File file = null;
		int totalAttachments ;
		
		try
		{
			//Get all the attachments
			AttachmentPart[] attachments = getMessageAttachments();

			/*
			 * getMessageAttachments() as provided by Steve Loughran in his mail
			 * to axis-user group
			 * http://www.mail-archive.com/axis-user@xml.apache.org/msg08732.html
			 */

			//Put the logic in a loop for totalAttachments for multiple
			// attachments.
			totalAttachments = attachments.length;
			_logger.debug("saveFile(String filename = " + filename + ") - " +
						"Total Attachments Received Are: "+ totalAttachments);
			
			if (totalAttachments != 1)
			{
				throw new AttachmentException("Too many attachments sent [" + attachments.length
						+ "] Please limit to 1");
			}
		
			//Extract the first attachment. (Since in this case we have only one attachment sent)
			DataHandler dh = attachments[0].getDataHandler();

			//Extract the file name of the first attachment.
			String name = filename;
			_logger.debug("saveFile(String filename = " + filename + ") - File received on server is: " + name);
			
			//Get the streams to file and from attachment, then stream to disk
			is = dh.getInputStream();
			file = new File(name);
			os = new FileOutputStream(file);
			this.writeBuffersAndClose(is, os);

		} catch (Exception e)
		{
			_logger.error("detachFile(String filename = " + filename + ")", e);

			throw new AttachmentException(e);
		}
		
		if(file!= null)
			return file;
		else 
			throw new AttachmentException("The attachment was not saved");

	}

	/**
	 * extract attachments from the current request
	 * 
	 * @return a list of attachmentparts or an empty array for no attachments
	 *         support in this axis buid/runtime
	 */
	private AttachmentPart[] getMessageAttachments() throws AxisFault
	{
		/*
		 * Reusing the method implementation for AttachmentPart[]
		 * getMessageAttachments() as provided by Steve Loughran in his mail to
		 * axis-user group
		 * http://www.mail-archive.com/axis-user@xml.apache.org/msg08732.html
		 */
		MessageContext msgContext = MessageContext.getCurrentContext();
		Message reqMsg = msgContext.getRequestMessage();
		Attachments messageAttachments = reqMsg.getAttachmentsImpl();
		if (null == messageAttachments)
		{
			System.out.println("no attachment support");
			return new AttachmentPart[0];
		}
		int attachmentCount = messageAttachments.getAttachmentCount();
		AttachmentPart attachments[] = new AttachmentPart[attachmentCount];
		Iterator it = messageAttachments.getAttachments().iterator();
		int count = 0;
		while (it.hasNext())
		{
			AttachmentPart part = (AttachmentPart) it.next();
			attachments[count++] = part;
		}
		return attachments;
	}

	
	/**
	 * Simple method for writing one stream from another.
	 * 
	 * @param is
	 * @param os
	 * @throws IOException
	 */
	private void writeBuffersAndClose(InputStream is, OutputStream os) 
		throws IOException
	{
		int i = 0;
		byte [] buffer = new byte[1024];
		while (i != -1)
		{
			i = is.read(buffer, 0, buffer.length);
			if(i > 0)
				os.write(buffer, 0, buffer.length);
		}
		is.close();
		os.close();
	}
}

Reply via email to