/* * 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.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory; import org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory; import org.apache.axis.transport.http.HTTPConstants; import org.apache.axis.utils.Options; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; import javax.xml.soap.AttachmentPart; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPBodyElement; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import java.io.File; import java.net.URL; import java.util.Hashtable; import java.util.Iterator; import java.util.ListIterator; import java.util.Vector; /** * * @author Rick Rineholt */ /** * An example of sending an attachment via RPC. * This class has a main method that beside the standard arguments * allows you to specify an attachment that will be sent to a * service which will then send it back. * */ public class EchoAttachment { Options opts = null; public EchoAttachment(Options opts) { this.opts = opts; } /** * This method sends a file as an attachment then * receives it as a return. The returned file is * compared to the source. * @param The filename that is the source to send. * @return True if sent and compared. */ public boolean echo(final boolean doTheDIME, String filename) throws Exception { //javax.activation.MimetypesFileTypeMap map= (javax.activation.MimetypesFileTypeMap)javax.activation.MimetypesFileTypeMap.getDefaultFileTypeMap(); //map.addMimeTypes("application/x-org-apache-axis-wsdd wsdd"); //Create the data for the attached file. DataHandler dhSource = new DataHandler(new FileDataSource(filename)); Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress(new URL(opts.getURL())); //Set the target service host and service location, call.setOperationName(new QName("urn:EchoAttachmentsService", "echo")); //This is the target services method to invoke. QName qnameAttachment = new QName("urn:EchoAttachmentsService", "DataHandler"); call.registerTypeMapping(dhSource.getClass(), //Add serializer for attachment. qnameAttachment, JAFDataHandlerSerializerFactory.class, JAFDataHandlerDeserializerFactory.class); call.addParameter("source", qnameAttachment, ParameterMode.IN); //Add the file. call.setReturnType(qnameAttachment); call.setUsername(opts.getUser()); call.setPassword(opts.getPassword()); if (doTheDIME) call.setProperty(call.ATTACHMENT_ENCAPSULATION_FORMAT, call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME); Object ret = call.invoke(new Object[]{ dhSource } ); //Add the attachment. 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); } if (!(ret instanceof DataHandler)) { //The wrong type of object that what was expected. System.out.println("Received problem response from server:" + ret.getClass().getName()); throw new AxisFault("", "Received problem response from server:" + ret.getClass().getName(), null, null); } //Still here, so far so good. //Now lets brute force compare the source attachment // to the one we received. DataHandler rdh = (DataHandler) ret; //From here we'll just treat the data resource as file. String receivedfileName = rdh.getName();//Get the filename. if (receivedfileName == null) { System.err.println("Could not get the file name."); throw new AxisFault("", "Could not get the file name.", null, null); } System.out.println("Going to compare the files.."); boolean retv = compareFiles(filename, receivedfileName); java.io.File receivedFile = new java.io.File(receivedfileName); receivedFile.delete(); return retv; } /** * 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 echoDir(final boolean doTheDIME, String filename) throws Exception { boolean rc = true; DataHandler[] attachments = getAttachmentsFromDir(filename); //Get the attachments from the directory. if (attachments.length == 0) { throw new java.lang.IllegalArgumentException( "The directory \"" + filename + "\" has no files to send."); } 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("dddd", "yyy"); //Send extra soap headers myhttp.put("SOAPAction", "dyyy"); myhttp.put("SOAPActions", "prova"); /*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, call.setOperationName(new QName("urn:EchoAttachmentsService", "echoDir")); //This is the target services method to invoke. QName qnameAttachment = new QName("urn:EchoAttachmentsService", "DataHandler"); call.registerTypeMapping(attachments[0].getClass(), //Add serializer for attachment. qnameAttachment, JAFDataHandlerSerializerFactory.class, JAFDataHandlerDeserializerFactory.class); call.addParameter("source", XMLType.SOAP_ARRAY, // new XMLType(qnameAttachment), ParameterMode.IN); //Add the file. call.setReturnType(XMLType.SOAP_ARRAY); // new XMLType(qnameAttachment)); call.setUsername(opts.getUser()); call.setPassword(opts.getPassword()); if (doTheDIME) call.setProperty(call.ATTACHMENT_ENCAPSULATION_FORMAT, call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME); Object ret = call.invoke(new Object[]{ attachments } ); //Add the attachment. 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); } if (!(ret instanceof javax.activation.DataHandler[])) { //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); } //Still here, so far so good. //Now lets brute force compare the source attachment // to the one we received. javax.activation.DataHandler[] received = (javax.activation.DataHandler[]) ret; int i = 0; for (i = 0; i < received.length && i < attachments.length; ++i) { DataHandler recDH = received[i]; DataHandler orginalDH = attachments[i]; if (!compareFiles(filename + java.io.File.separator + orginalDH.getName(), recDH.getName())) { System.err.println("The attachment with the file name: \"" + orginalDH.getName() + "\" was not received the same!."); rc = false; } java.io.File receivedFile = new java.io.File(recDH.getName()); receivedFile.delete(); } if (i < received.length) { System.err.println("There are more file received than sent!!!!"); rc = false; } if (i < attachments.length) { System.err.println("Not all the files were received!"); rc = false; } return rc; } /** * 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); EchoAttachment echoattachment = new EchoAttachment(opts); args = opts.getRemainingArgs(); int argpos = 0; if (args == null || args.length == 0) { System.err.println("Need a file or directory argument."); System.exit(8); } boolean doTheDIME = false; if (args[0].trim().equalsIgnoreCase("+FDR")) { doTheDIME = true; ++argpos; } if (argpos >= args.length) { System.err.println("Need a file or directory argument."); System.exit(8); } String argFile = args[argpos]; java.io.File source = new java.io.File(argFile); if (!source.exists()) { System.err.println("Error \"" + argFile + "\" does not exist!"); System.exit(8); } if (source.isFile()) { if (echoattachment.echoUsingSAAJ(argFile) && echoattachment.echo(doTheDIME, argFile)) { System.out.println("Attachment sent and received ok!"); System.exit(0); } else { System.err.println("Problem in matching attachments"); System.exit(8); } } else { //a directory? if (echoattachment.echoDir(doTheDIME, argFile)) { System.out.println("Attachments sent and received ok!"); System.exit(0); } else { System.err.println("Problem in matching attachments"); System.exit(8); } } } catch (Exception e) { System.err.println(e); e.printStackTrace(); } System.exit(18); } /** * Quick and unsophisticated method to compare two file's * byte stream. * @param The first file to compare. * @param The second file to compare. * @return True if the bytestreams do compare, false for * any other reason. */ protected boolean compareFiles(String one, String other) throws java.io.FileNotFoundException, java.io.IOException { java.io.BufferedInputStream oneStream = null; java.io.BufferedInputStream otherStream = null; // First compare file length. File f1 = new File(one); File f2 = new File(other); if (f1.length() != f2.length()) return false; try { oneStream = new java.io.BufferedInputStream( new java.io.FileInputStream(one), 1024 * 64); otherStream = new java.io.BufferedInputStream( new java.io.FileInputStream(other), 1024 * 64); byte[] bufOne = new byte[1024 * 64]; byte[] bufOther = new byte[1024 * 64]; int breadOne = -1; int breadOther = -1; int available = 0; do { available = oneStream.available(); available = Math.min(available, otherStream.available()); available = Math.min(available, bufOther.length); if (0 != available) { java.util.Arrays.fill(bufOne, (byte) 0); java.util.Arrays.fill(bufOther, (byte) 0); breadOne = oneStream.read(bufOne, 0, available); breadOther = otherStream.read(bufOther, 0, available); if (breadOne != breadOther) throw new RuntimeException( "Sorry couldn't really read whats available!"); if (!java.util.Arrays.equals(bufOne, bufOther)) { return false; } } } while (available != 0 && breadOne != -1 && breadOther != -1); if (available != 0 && (breadOne != -1 || breadOther != -1)) { return false; } return true; } finally { if (null != oneStream) oneStream.close(); if (null != otherStream) otherStream.close(); } } /** * 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 method sends a file as an attachment then * receives it as a return. The returned file is * compared to the source. Uses SAAJ API. * @param The filename that is the source to send. * @return True if sent and compared. */ public boolean echoUsingSAAJ(String filename) throws Exception { String endPointURLString = "http://localhost:" +opts.getPort() + "/axis/services/urn:EchoAttachmentsService"; SOAPConnectionFactory soapConnectionFactory = javax.xml.soap.SOAPConnectionFactory.newInstance(); SOAPConnection soapConnection = soapConnectionFactory.createConnection(); MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); SOAPPart soapPart = soapMessage.getSOAPPart(); SOAPEnvelope requestEnvelope = soapPart.getEnvelope(); SOAPBody body = requestEnvelope.getBody(); SOAPBodyElement operation = body.addBodyElement (requestEnvelope.createName("echo")); Vector dataHandlersToAdd = new Vector(); dataHandlersToAdd.add(new DataHandler(new FileDataSource(new File(filename)))); if (dataHandlersToAdd != null) { ListIterator dataHandlerIterator = dataHandlersToAdd.listIterator(); while (dataHandlerIterator.hasNext()) { DataHandler dataHandler = (DataHandler) dataHandlerIterator.next(); javax.xml.soap.SOAPElement element = operation.addChildElement(requestEnvelope.createName("source")); javax.xml.soap.AttachmentPart attachment = soapMessage.createAttachmentPart(dataHandler); soapMessage.addAttachmentPart(attachment); element.addAttribute(requestEnvelope.createName ("href"), "cid:" + attachment.getContentId()); } } javax.xml.soap.SOAPMessage returnedSOAPMessage = soapConnection.call(soapMessage, endPointURLString); Iterator iterator = returnedSOAPMessage.getAttachments(); if (!iterator.hasNext()) { //The wrong type of object that what was expected. System.out.println("Received problem response from server"); throw new AxisFault("", "Received problem response from server", null, null); } //Still here, so far so good. //Now lets brute force compare the source attachment // to the one we received. DataHandler rdh = (DataHandler) ((AttachmentPart)iterator.next()).getDataHandler(); //From here we'll just treat the data resource as file. String receivedfileName = rdh.getName();//Get the filename. if (receivedfileName == null) { System.err.println("Could not get the file name."); throw new AxisFault("", "Could not get the file name.", null, null); } System.out.println("Going to compare the files.."); boolean retv = compareFiles(filename, receivedfileName); java.io.File receivedFile = new java.io.File(receivedfileName); receivedFile.delete(); return retv; } }