/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package samples.attachments;
import org.apache.axis.AxisFault;
import org.apache.axis.attachments.AttachmentPart;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.utils.Options;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.Hashtable;
import java.util.Vector;
/**
*
* @author Rick Rineholt
*/
/**
* An example of sending an attachment via messages.
* The main purpose is to validate the different types of attachment references
* by content Id, content location both absolute and relative.
*
* Creates 5 separate attachments referenced differently by a SOAP document.
* Each attachment contains a string that is assembled and tested to see if
* if the attachments are correctly sent and referenced. Each attachment also
* contains a mime header indicating its position and validated on the server
* to see if mime headers are correctly sent with attachments.
*
* Sends the same message again however the second attachments are placed in the
* stream in reverse to see if they are still referenced ok.
*
*
* The return SOAP document references a single attachment which is the a Java
* serialized vector holding strings to the individual attachments sent.
*
* Demos using attachments directly.
*
*/
public class TestRef {
Options opts = null;
public static final String positionHTTPHeader="Ordinal";
public static final String TheKey= "Now is the time for all good men to come to the aid of their country.";
public TestRef( Options opts) {
this.opts = opts;
}
/**
* This method sends all the files in a directory.
* @param The directory that is the source to send.
* @return True if sent and compared.
*/
public boolean testit() throws Exception {
boolean rc = true;
String baseLoc= "http://axis.org/attachTest";
Vector refs= new Vector(); //holds a string of references to attachments.
Service service = new Service(); //A new axis Service.
Call call = (Call) service.createCall(); //Create a call to the service.
/*Un comment the below statement to do HTTP/1.1 protocol*/
//call.setScopedProperty(MessageContext.HTTP_TRANSPORT_VERSION,HTTPConstants.HEADER_PROTOCOL_V11);
Hashtable myhttp= new Hashtable();
myhttp.put(HTTPConstants.HEADER_CONTENT_LOCATION, baseLoc); //Send extra soap headers
/*Un comment the below to do http chunking to avoid the need to calculate content-length. (Needs HTTP/1.1)*/
//myhttp.put(HTTPConstants.HEADER_TRANSFER_ENCODING, HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED);
/*Un comment the below to force a 100-Continue... This will cause httpsender to wait for
* this response on a post. If HTTP 1.1 and this is not set, *SOME* servers *MAY* reply with this anyway.
* Currently httpsender won't handle this situation, this will require the resp. which it will handle.
*/
//myhttp.put(HTTPConstants.HEADER_EXPECT, HTTPConstants.HEADER_EXPECT_100_Continue);
call.setProperty(HTTPConstants.REQUEST_HEADERS,myhttp);
call.setTargetEndpointAddress( new URL(opts.getURL()) ); //Set the target service host and service location,
java.util.Stack rev= new java.util.Stack();
//Create an attachment referenced by a generated contentId.
AttachmentPart ap= new AttachmentPart(new javax.activation.DataHandler(
"Now is the time", "text/plain" ));
refs.add(ap.getContentIdRef()); //reference the attachment by contentId.
ap.setMimeHeader(positionHTTPHeader, ""+refs.size() ); //create a MIME header indicating postion.
call.addAttachmentPart(ap);
rev.push(ap);
//Create an attachment referenced by a set contentId.
String setContentId="rick_did_this";
ap= new AttachmentPart(new DataHandler(" for all good", "text/plain" ));
//new MemoryOnlyDataSource(
ap.setContentId(setContentId);
refs.add("cid:" + setContentId); //reference the attachment by contentId.
ap.setMimeHeader(positionHTTPHeader, ""+refs.size() ); //create a MIME header indicating postion.
call.addAttachmentPart(ap);
rev.push(ap);
//Create an attachment referenced by a absolute contentLocation.
ap= new AttachmentPart(new DataHandler( " men to", "text/plain" ));
//new MemoryOnlyDataSource( " men to", "text/plain" )));
ap.setContentLocation(baseLoc+ "/firstLoc");
refs.add(baseLoc+ "/firstLoc"); //reference the attachment by contentId.
ap.setMimeHeader(positionHTTPHeader, ""+refs.size() ); //create a MIME header indicating postion.
call.addAttachmentPart(ap);
rev.push(ap);
//Create an attachment referenced by relative location to a absolute location.
ap= new AttachmentPart(new DataHandler( " come to", "text/plain" ));
// new MemoryOnlyDataSource( " come to", "text/plain" )));
ap.setContentLocation(baseLoc+ "/secondLoc");
refs.add("secondLoc"); //reference the attachment by contentId.
ap.setMimeHeader(positionHTTPHeader, ""+refs.size() ); //create a MIME header indicating postion.
call.addAttachmentPart(ap);
rev.push(ap);
//Create an attachment referenced by relative location to a relative location.
ap= new AttachmentPart(new DataHandler( " the aid of their country.", "text/plain" ));
// new MemoryOnlyDataSource( " the aid of their country.", "text/plain" )));
ap.setContentLocation("thirdLoc");
refs.add("thirdLoc"); //reference the attachment by contentId.
ap.setMimeHeader(positionHTTPHeader, ""+refs.size() ); //create a MIME header indicating postion.
call.addAttachmentPart(ap);
rev.push(ap);
//Now build the message....
String namespace="urn:attachmentsTestRef"; //needs to match name of service.
StringBuffer msg = new StringBuffer("\n<attachments xmlns=\"" +namespace +"\">\n");
for (java.util.Iterator i = refs.iterator(); i.hasNext() ; )
msg.append(" <attachment href=\"" + (String) i.next() + "\"/>\n");
msg.append( "</attachments>");
call.setUsername( opts.getUser());
call.setPassword( opts.getPassword() );
call.setOperationStyle("document");
call.setOperationUse("literal");
//Now do the call....
Object ret = call.invoke(new Object[]{
new SOAPBodyElement(new ByteArrayInputStream(msg.toString().getBytes("UTF-8"))) } );
validate(ret, call, "12345");
//Note: that even though the attachments are sent in reverse they are still
// retreived by reference so the ordinal will still match.
int revc=1;
for( ap= (AttachmentPart)rev.pop(); ap!=null ;ap= rev.empty()? null : (AttachmentPart)rev.pop()){
call.addAttachmentPart(ap);
}
//Now do the call....
ret = call.invoke(new Object[]{
new SOAPBodyElement(new ByteArrayInputStream(msg.toString().getBytes("UTF-8"))) } );
validate(ret, call, "54321");
return rc;
}
void validate(Object ret, Call call, final String expOrdPattern) throws Exception{
if (null == ret) {
System.out.println("Received null ");
throw new AxisFault("", "Received null", null, null);
}
if (ret instanceof String) {
System.out.println("Received problem response from server: " + ret);
throw new AxisFault("", (String) ret, null, null);
}
Vector vret= (Vector) ret;
if (!(ret instanceof java.util.Vector )) {
//The wrong type of object that what was expected.
System.out.println("Received unexpected type :" +
ret.getClass().getName());
throw new AxisFault("", "Received unexpected type:" +
ret.getClass().getName(), null, null);
}
org.apache.axis.message.RPCElement retrpc= (org.apache.axis.message.RPCElement )
((Vector)ret).elementAt(0);
Document retDoc= org.apache.axis.utils.XMLUtils.newDocument(
new org.xml.sax.InputSource(new java.io.ByteArrayInputStream(
retrpc.toString().getBytes())));
//get at the attachments.
org.apache.axis.attachments.Attachments attachments=
call.getResponseMessage().getAttachmentsImpl();
//Still here, so far so good.
Element rootEl= retDoc.getDocumentElement();
Element caEl= getNextFirstChildElement(rootEl);
//this should be the only child element with the ref to our attachment
// response.
String href= caEl.getAttribute("href");
org.apache.axis.Part p= attachments.getAttachmentByReference(href);
if(null == p)
throw new org.apache.axis.AxisFault("Attachment for ref='"+href+"' not found." );
//Check to see the the attachment were sent in order
String ordPattern= caEl.getAttribute("ordinalPattern");
if(!expOrdPattern.equals(ordPattern))
throw new org.apache.axis.AxisFault(
"Attachments sent out of order expected:'" +expOrdPattern + "', got:'"+ordPattern+"'." );
//now get at the data...
DataHandler dh= ((org.apache.axis.attachments.AttachmentPart)p).getDataHandler();
System.err.println("content-type:" + dh.getContentType());
java.util.Vector rspVector= null;
Object rspObject = dh.getContent();//This SHOULD just return the vector but reality strikes...
if(rspObject == null)
throw new AxisFault("", "Received unexpected object:null", null, null);
else if(rspObject instanceof java.util.Vector) rspVector= (java.util.Vector)rspObject;
else if(rspObject instanceof java.io.InputStream)
rspVector= (java.util.Vector)
new java.io.ObjectInputStream((java.io.InputStream)rspObject ).readObject();
else
throw new AxisFault("", "Received unexpected object:" +
rspObject.getClass().getName(), null, null);
StringBuffer fullmsg= new StringBuffer();
for(java.util.Iterator ri= rspVector.iterator(); ri.hasNext();){
String part= (String)ri.next();
fullmsg.append(part);
System.out.print(part);
}
System.out.println("");
if(!(TheKey.equals (fullmsg.toString())))
throw new org.apache.axis.AxisFault("Fullmsg not correct'"+fullmsg +"'." );
}
Element getNextFirstChildElement(Node n) {
if(n== null) return null;
n= n.getFirstChild();
for(; n!= null && !(n instanceof Element); n= n.getNextSibling());
return (Element)n;
}
Element getNextSiblingElement(Node n) {
if(n== null) return null;
n= n.getNextSibling();
for(; n!= null && !(n instanceof Element); n= n.getNextSibling());
return (Element)n;
}
/**
* Give a single file to send or name a directory
* to send an array of attachments of the files in
* that directory.
*/
public static void main(String args[]) {
try {
Options opts = new Options(args);
TestRef echoattachment = new TestRef(opts);
args = opts.getRemainingArgs();
int argpos=0;
if (echoattachment.testit()) {
System.out.println("Attachments sent and received ok!");
System.exit(0);
}
}
catch ( Exception e ) {
System.err.println(e);
e.printStackTrace();
}
System.exit(18);
}
/**
* Return an array of datahandlers for each file in the dir.
* @param the name of the directory
* @return return an array of datahandlers.
*/
protected DataHandler[] getAttachmentsFromDir(String dirName) {
java.util.LinkedList retList = new java.util.LinkedList();
DataHandler[] ret = new DataHandler[0];// empty
java.io.File sourceDir = new java.io.File(dirName);
java.io.File[] files = sourceDir.listFiles();
for ( int i = files.length - 1; i >= 0; --i) {
java.io.File cf = files[i];
if (cf.isFile() && cf.canRead()) {
String fname = null;
try {
fname = cf.getAbsoluteFile().getCanonicalPath();
}
catch ( java.io.IOException e) {
System.err.println("Couldn't get file \"" + fname + "\" skipping...");
continue;
}
retList.add( new DataHandler( new FileDataSource( fname )));
}
}
if (!retList.isEmpty()) {
ret = new DataHandler[ retList.size()];
ret = (DataHandler[]) retList.toArray(ret);
}
return ret;
}
/**This class should store all attachment data in memory */
static class MemoryOnlyDataSource extends org.apache.axis.attachments.ManagedMemoryDataSource{
MemoryOnlyDataSource( byte [] in, String contentType) throws java.io.IOException{
super( new java.io.ByteArrayInputStream( in) , Integer.MAX_VALUE -2, contentType, true);
}
MemoryOnlyDataSource( String in, String contentType)throws java.io.IOException{
this( in.getBytes() , contentType);
}
}
}
|