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
- John Walker
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();
}
}