001: /*
002: * Copyright 2001-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package samples.attachments;
018:
019: import org.apache.axis.AxisFault;
020: import org.apache.axis.client.Call;
021: import org.apache.axis.client.Service;
022: import org.apache.axis.encoding.XMLType;
023: import org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory;
024: import org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory;
025: import org.apache.axis.transport.http.HTTPConstants;
026: import org.apache.axis.utils.Options;
027:
028: import javax.activation.DataHandler;
029: import javax.activation.FileDataSource;
030: import javax.xml.namespace.QName;
031: import javax.xml.rpc.ParameterMode;
032: import javax.xml.soap.AttachmentPart;
033: import javax.xml.soap.MessageFactory;
034: import javax.xml.soap.SOAPBody;
035: import javax.xml.soap.SOAPBodyElement;
036: import javax.xml.soap.SOAPConnection;
037: import javax.xml.soap.SOAPConnectionFactory;
038: import javax.xml.soap.SOAPEnvelope;
039: import javax.xml.soap.SOAPMessage;
040: import javax.xml.soap.SOAPPart;
041: import java.io.File;
042: import java.net.URL;
043: import java.util.Hashtable;
044: import java.util.Iterator;
045: import java.util.ListIterator;
046: import java.util.Vector;
047:
048: /**
049: *
050: * @author Rick Rineholt
051: */
052:
053: /**
054: * An example of sending an attachment via RPC.
055: * This class has a main method that beside the standard arguments
056: * allows you to specify an attachment that will be sent to a
057: * service which will then send it back.
058: *
059: */
060: public class EchoAttachment {
061:
062: Options opts = null;
063:
064: public EchoAttachment(Options opts) {
065: this .opts = opts;
066: }
067:
068: /**
069: * This method sends a file as an attachment then
070: * receives it as a return. The returned file is
071: * compared to the source.
072: * @param The filename that is the source to send.
073: * @return True if sent and compared.
074: */
075: public boolean echo(final boolean doTheDIME, String filename)
076: throws Exception {
077:
078: //javax.activation.MimetypesFileTypeMap map= (javax.activation.MimetypesFileTypeMap)javax.activation.MimetypesFileTypeMap.getDefaultFileTypeMap();
079: //map.addMimeTypes("application/x-org-apache-axis-wsdd wsdd");
080:
081: //Create the data for the attached file.
082: DataHandler dhSource = new DataHandler(new FileDataSource(
083: filename));
084:
085: Service service = new Service();
086:
087: Call call = (Call) service.createCall();
088:
089: call.setTargetEndpointAddress(new URL(opts.getURL())); //Set the target service host and service location,
090:
091: call.setOperationName(new QName("urn:EchoAttachmentsService",
092: "echo")); //This is the target services method to invoke.
093:
094: QName qnameAttachment = new QName("urn:EchoAttachmentsService",
095: "DataHandler");
096:
097: call.registerTypeMapping(
098: dhSource.getClass(), //Add serializer for attachment.
099: qnameAttachment, JAFDataHandlerSerializerFactory.class,
100: JAFDataHandlerDeserializerFactory.class);
101:
102: call.addParameter("source", qnameAttachment, ParameterMode.IN); //Add the file.
103:
104: call.setReturnType(qnameAttachment);
105:
106: call.setUsername(opts.getUser());
107:
108: call.setPassword(opts.getPassword());
109:
110: if (doTheDIME)
111: call.setProperty(call.ATTACHMENT_ENCAPSULATION_FORMAT,
112: call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME);
113:
114: Object ret = call.invoke(new Object[] { dhSource }); //Add the attachment.
115:
116: if (null == ret) {
117: System.out.println("Received null ");
118: throw new AxisFault("", "Received null", null, null);
119: }
120:
121: if (ret instanceof String) {
122: System.out
123: .println("Received problem response from server: "
124: + ret);
125: throw new AxisFault("", (String) ret, null, null);
126: }
127:
128: if (!(ret instanceof DataHandler)) {
129: //The wrong type of object that what was expected.
130: System.out.println("Received problem response from server:"
131: + ret.getClass().getName());
132: throw new AxisFault("",
133: "Received problem response from server:"
134: + ret.getClass().getName(), null, null);
135:
136: }
137: //Still here, so far so good.
138: //Now lets brute force compare the source attachment
139: // to the one we received.
140: DataHandler rdh = (DataHandler) ret;
141:
142: //From here we'll just treat the data resource as file.
143: String receivedfileName = rdh.getName();//Get the filename.
144:
145: if (receivedfileName == null) {
146: System.err.println("Could not get the file name.");
147: throw new AxisFault("", "Could not get the file name.",
148: null, null);
149: }
150:
151: System.out.println("Going to compare the files..");
152: boolean retv = compareFiles(filename, receivedfileName);
153:
154: java.io.File receivedFile = new java.io.File(receivedfileName);
155:
156: receivedFile.delete();
157:
158: return retv;
159: }
160:
161: /**
162: * This method sends all the files in a directory.
163: * @param The directory that is the source to send.
164: * @return True if sent and compared.
165: */
166: public boolean echoDir(final boolean doTheDIME, String filename)
167: throws Exception {
168: boolean rc = true;
169:
170: DataHandler[] attachments = getAttachmentsFromDir(filename); //Get the attachments from the directory.
171:
172: if (attachments.length == 0) {
173: throw new java.lang.IllegalArgumentException(
174: "The directory \"" + filename
175: + "\" has no files to send.");
176: }
177:
178: Service service = new Service(); //A new axis Service.
179:
180: Call call = (Call) service.createCall(); //Create a call to the service.
181:
182: /*Un comment the below statement to do HTTP/1.1 protocol*/
183: //call.setScopedProperty(MessageContext.HTTP_TRANSPORT_VERSION,HTTPConstants.HEADER_PROTOCOL_V11);
184: Hashtable myhttp = new Hashtable();
185: myhttp.put("dddd", "yyy"); //Send extra soap headers
186: myhttp.put("SOAPAction", "dyyy");
187: myhttp.put("SOAPActions", "prova");
188:
189: /*Un comment the below to do http chunking to avoid the need to calculate content-length. (Needs HTTP/1.1)*/
190: //myhttp.put(HTTPConstants.HEADER_TRANSFER_ENCODING, HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED);
191: /*Un comment the below to force a 100-Continue... This will cause httpsender to wait for
192: * this response on a post. If HTTP 1.1 and this is not set, *SOME* servers *MAY* reply with this anyway.
193: * Currently httpsender won't handle this situation, this will require the resp. which it will handle.
194: */
195: //myhttp.put(HTTPConstants.HEADER_EXPECT, HTTPConstants.HEADER_EXPECT_100_Continue);
196: call.setProperty(HTTPConstants.REQUEST_HEADERS, myhttp);
197:
198: call.setTargetEndpointAddress(new URL(opts.getURL())); //Set the target service host and service location,
199:
200: call.setOperationName(new QName("urn:EchoAttachmentsService",
201: "echoDir")); //This is the target services method to invoke.
202:
203: QName qnameAttachment = new QName("urn:EchoAttachmentsService",
204: "DataHandler");
205:
206: call.registerTypeMapping(
207: attachments[0].getClass(), //Add serializer for attachment.
208: qnameAttachment, JAFDataHandlerSerializerFactory.class,
209: JAFDataHandlerDeserializerFactory.class);
210:
211: call.addParameter("source", XMLType.SOAP_ARRAY, // new XMLType(qnameAttachment),
212: ParameterMode.IN); //Add the file.
213:
214: call.setReturnType(XMLType.SOAP_ARRAY); // new XMLType(qnameAttachment));
215:
216: call.setUsername(opts.getUser());
217:
218: call.setPassword(opts.getPassword());
219:
220: if (doTheDIME)
221: call.setProperty(call.ATTACHMENT_ENCAPSULATION_FORMAT,
222: call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME);
223:
224: Object ret = call.invoke(new Object[] { attachments }); //Add the attachment.
225:
226: if (null == ret) {
227: System.out.println("Received null ");
228: throw new AxisFault("", "Received null", null, null);
229: }
230:
231: if (ret instanceof String) {
232: System.out
233: .println("Received problem response from server: "
234: + ret);
235: throw new AxisFault("", (String) ret, null, null);
236: }
237:
238: if (!(ret instanceof javax.activation.DataHandler[])) {
239: //The wrong type of object that what was expected.
240: System.out.println("Received unexpected type :"
241: + ret.getClass().getName());
242: throw new AxisFault("", "Received unexpected type:"
243: + ret.getClass().getName(), null, null);
244:
245: }
246: //Still here, so far so good.
247: //Now lets brute force compare the source attachment
248: // to the one we received.
249: javax.activation.DataHandler[] received = (javax.activation.DataHandler[]) ret;
250:
251: int i = 0;
252: for (i = 0; i < received.length && i < attachments.length; ++i) {
253: DataHandler recDH = received[i];
254: DataHandler orginalDH = attachments[i];
255:
256: if (!compareFiles(filename + java.io.File.separator
257: + orginalDH.getName(), recDH.getName())) {
258: System.err
259: .println("The attachment with the file name: \""
260: + orginalDH.getName()
261: + "\" was not received the same!.");
262: rc = false;
263: }
264: java.io.File receivedFile = new java.io.File(recDH
265: .getName());
266:
267: receivedFile.delete();
268: }
269:
270: if (i < received.length) {
271: System.err
272: .println("There are more file received than sent!!!!");
273:
274: rc = false;
275: }
276: if (i < attachments.length) {
277: System.err.println("Not all the files were received!");
278: rc = false;
279: }
280:
281: return rc;
282: }
283:
284: /**
285: * Give a single file to send or name a directory
286: * to send an array of attachments of the files in
287: * that directory.
288: */
289: public static void main(String args[]) {
290: try {
291:
292: Options opts = new Options(args);
293: EchoAttachment echoattachment = new EchoAttachment(opts);
294:
295: args = opts.getRemainingArgs();
296: int argpos = 0;
297:
298: if (args == null || args.length == 0) {
299: System.err
300: .println("Need a file or directory argument.");
301: System.exit(8);
302: }
303:
304: boolean doTheDIME = false;
305: if (args[0].trim().equalsIgnoreCase("+FDR")) {
306: doTheDIME = true;
307: ++argpos;
308: }
309:
310: if (argpos >= args.length) {
311: System.err
312: .println("Need a file or directory argument.");
313: System.exit(8);
314: }
315:
316: String argFile = args[argpos];
317:
318: java.io.File source = new java.io.File(argFile);
319:
320: if (!source.exists()) {
321: System.err.println("Error \"" + argFile
322: + "\" does not exist!");
323: System.exit(8);
324: }
325:
326: if (source.isFile()) {
327: if (echoattachment.echoUsingSAAJ(argFile)
328: && echoattachment.echo(doTheDIME, argFile)) {
329: System.out
330: .println("Attachment sent and received ok!");
331: System.exit(0);
332: } else {
333: System.err
334: .println("Problem in matching attachments");
335: System.exit(8);
336: }
337: } else { //a directory?
338: if (echoattachment.echoDir(doTheDIME, argFile)) {
339: System.out
340: .println("Attachments sent and received ok!");
341: System.exit(0);
342: } else {
343: System.err
344: .println("Problem in matching attachments");
345: System.exit(8);
346: }
347: }
348: } catch (Exception e) {
349: System.err.println(e);
350: e.printStackTrace();
351: }
352: System.exit(18);
353: }
354:
355: /**
356: * Quick and unsophisticated method to compare two file's
357: * byte stream.
358: * @param The first file to compare.
359: * @param The second file to compare.
360: * @return True if the bytestreams do compare, false for
361: * any other reason.
362: */
363: protected boolean compareFiles(String one, String other)
364: throws java.io.FileNotFoundException, java.io.IOException {
365:
366: java.io.BufferedInputStream oneStream = null;
367: java.io.BufferedInputStream otherStream = null;
368:
369: // First compare file length.
370: File f1 = new File(one);
371: File f2 = new File(other);
372: if (f1.length() != f2.length())
373: return false;
374:
375: try {
376: oneStream = new java.io.BufferedInputStream(
377: new java.io.FileInputStream(one), 1024 * 64);
378: otherStream = new java.io.BufferedInputStream(
379: new java.io.FileInputStream(other), 1024 * 64);
380:
381: byte[] bufOne = new byte[1024 * 64];
382: byte[] bufOther = new byte[1024 * 64];
383: int breadOne = -1;
384: int breadOther = -1;
385: int available = 0;
386:
387: do {
388: available = oneStream.available();
389: available = Math
390: .min(available, otherStream.available());
391: available = Math.min(available, bufOther.length);
392:
393: if (0 != available) {
394: java.util.Arrays.fill(bufOne, (byte) 0);
395: java.util.Arrays.fill(bufOther, (byte) 0);
396:
397: breadOne = oneStream.read(bufOne, 0, available);
398: breadOther = otherStream.read(bufOther, 0,
399: available);
400: if (breadOne != breadOther)
401: throw new RuntimeException(
402: "Sorry couldn't really read whats available!");
403: if (!java.util.Arrays.equals(bufOne, bufOther)) {
404: return false;
405: }
406: }
407:
408: } while (available != 0 && breadOne != -1
409: && breadOther != -1);
410: if (available != 0 && (breadOne != -1 || breadOther != -1)) {
411: return false;
412: }
413: return true;
414: } finally {
415: if (null != oneStream)
416: oneStream.close();
417: if (null != otherStream)
418: otherStream.close();
419: }
420: }
421:
422: /**
423: * Return an array of datahandlers for each file in the dir.
424: * @param the name of the directory
425: * @return return an array of datahandlers.
426: */
427:
428: protected DataHandler[] getAttachmentsFromDir(String dirName) {
429: java.util.LinkedList retList = new java.util.LinkedList();
430: DataHandler[] ret = new DataHandler[0];// empty
431:
432: java.io.File sourceDir = new java.io.File(dirName);
433:
434: java.io.File[] files = sourceDir.listFiles();
435:
436: for (int i = files.length - 1; i >= 0; --i) {
437: java.io.File cf = files[i];
438:
439: if (cf.isFile() && cf.canRead()) {
440: String fname = null;
441:
442: try {
443: fname = cf.getAbsoluteFile().getCanonicalPath();
444: } catch (java.io.IOException e) {
445: System.err.println("Couldn't get file \"" + fname
446: + "\" skipping...");
447: continue;
448: }
449: retList.add(new DataHandler(new FileDataSource(fname)));
450: }
451: }
452: if (!retList.isEmpty()) {
453: ret = new DataHandler[retList.size()];
454: ret = (DataHandler[]) retList.toArray(ret);
455: }
456:
457: return ret;
458: }
459:
460: /**
461: * This method sends a file as an attachment then
462: * receives it as a return. The returned file is
463: * compared to the source. Uses SAAJ API.
464: * @param The filename that is the source to send.
465: * @return True if sent and compared.
466: */
467: public boolean echoUsingSAAJ(String filename) throws Exception {
468: String endPointURLString = "http://localhost:" + opts.getPort()
469: + "/axis/services/urn:EchoAttachmentsService";
470:
471: SOAPConnectionFactory soapConnectionFactory = javax.xml.soap.SOAPConnectionFactory
472: .newInstance();
473: SOAPConnection soapConnection = soapConnectionFactory
474: .createConnection();
475:
476: MessageFactory messageFactory = MessageFactory.newInstance();
477: SOAPMessage soapMessage = messageFactory.createMessage();
478: SOAPPart soapPart = soapMessage.getSOAPPart();
479: SOAPEnvelope requestEnvelope = soapPart.getEnvelope();
480: SOAPBody body = requestEnvelope.getBody();
481: SOAPBodyElement operation = body.addBodyElement(requestEnvelope
482: .createName("echo"));
483:
484: Vector dataHandlersToAdd = new Vector();
485: dataHandlersToAdd.add(new DataHandler(new FileDataSource(
486: new File(filename))));
487:
488: if (dataHandlersToAdd != null) {
489: ListIterator dataHandlerIterator = dataHandlersToAdd
490: .listIterator();
491:
492: while (dataHandlerIterator.hasNext()) {
493: DataHandler dataHandler = (DataHandler) dataHandlerIterator
494: .next();
495: javax.xml.soap.SOAPElement element = operation
496: .addChildElement(requestEnvelope
497: .createName("source"));
498: javax.xml.soap.AttachmentPart attachment = soapMessage
499: .createAttachmentPart(dataHandler);
500: soapMessage.addAttachmentPart(attachment);
501: element.addAttribute(
502: requestEnvelope.createName("href"), "cid:"
503: + attachment.getContentId());
504: }
505: }
506: javax.xml.soap.SOAPMessage returnedSOAPMessage = soapConnection
507: .call(soapMessage, endPointURLString);
508: Iterator iterator = returnedSOAPMessage.getAttachments();
509: if (!iterator.hasNext()) {
510: //The wrong type of object that what was expected.
511: System.out.println("Received problem response from server");
512: throw new AxisFault("",
513: "Received problem response from server", null, null);
514:
515: }
516: //Still here, so far so good.
517: //Now lets brute force compare the source attachment
518: // to the one we received.
519: DataHandler rdh = (DataHandler) ((AttachmentPart) iterator
520: .next()).getDataHandler();
521:
522: //From here we'll just treat the data resource as file.
523: String receivedfileName = rdh.getName();//Get the filename.
524:
525: if (receivedfileName == null) {
526: System.err.println("Could not get the file name.");
527: throw new AxisFault("", "Could not get the file name.",
528: null, null);
529: }
530:
531: System.out.println("Going to compare the files..");
532: boolean retv = compareFiles(filename, receivedfileName);
533:
534: java.io.File receivedFile = new java.io.File(receivedfileName);
535:
536: receivedFile.delete();
537:
538: return retv;
539: }
540: }
|